Getting read access violation exception in VC++ ho

2019-08-14 07:51发布

问题:

I'm using MS Visual Studio 2015 to develop a small app using VC++ and backend as SQLite. However using standard SQLite3 C api there are no exceptions occurring.

But when i tried to make a small wrapper for using SQLite. I made one header file for simplification for using functions as SQLite APIs. I'm getting read access violation exception. How to handle this exception and what changes i should make in my small wrapper so i can use it in multiple modules of the app.

here is my small wrapper SQLite.cpp:

#include "inc\sqlite3.h"
#include <string.h>
#pragma once

class SQLiteConnection {
    sqlite3 * conn;
public:
       SQLiteConnection() {
            conn = NULL;
        }
       ~SQLiteConnection() {
            sqlite3_close(conn);
        }

        int connect(char const * dbName) {

            int res = sqlite3_open(dbName, &conn);
            if (SQLITE_OK != res) {
                 printf("%s\n", sqlite3_errmsg(conn));
                 return res;
            }
            return res;
        }
        sqlite3 * getConn() {
            return conn;
        }
};

class Statement {
       sqlite3_stmt * stmt;
 public:
     Statement() {
         stmt = NULL;
     }
     int prepare(sqlite3 *,char *);
     int bind_param_int(sqlite3 *,int , int);
     int bind_param_text(sqlite3 * ,int , char const *);
     int bind_param_double(sqlite3 * ,int , double);
     bool step();
     int reset();
     char const * getColText(int idx);
     void finalize() {
         sqlite3_finalize(stmt);
     }
};
int Statement::prepare(sqlite3 * conn, char *sql) {
    int result;
    result = sqlite3_prepare_v2(conn, sql, -1, &stmt, NULL);

    if (SQLITE_OK != result) {
        sqlite3_errmsg(conn);
        return 0;           
    }
    return SQLITE_OK;
}
int Statement::bind_param_int(sqlite3 * conn,int idx, int val) {
     int res;
     res = sqlite3_bind_int(stmt, idx, val);
     if (SQLITE_OK != res) {
         sqlite3_errmsg(conn);
         return 0;
      }
      return SQLITE_OK;
}

int Statement::bind_param_text(sqlite3 * conn, int idx, char const * val) {
      int res;
      res = sqlite3_bind_text(stmt, idx, val, strlen(val)+1, SQLITE_STATIC);
      if (SQLITE_OK != res) {
          sqlite3_errmsg(conn);
          return 0;
      }
      return SQLITE_OK;
}
int Statement::bind_param_double(sqlite3 * conn , int idx, double val) {
      int res;
      res = sqlite3_bind_double(stmt, idx, val);
      if (SQLITE_OK != res) {
           sqlite3_errmsg(conn);
           return 0;
       }
       return SQLITE_OK;
}
bool Statement::step() {
      int res = sqlite3_step(stmt);
      if (SQLITE_DONE == res) return true;
      if (SQLITE_ROW == res) return true;
      return false;
}
int Statement::reset() {
      int res = sqlite3_reset(stmt);
      if (SQLITE_OK == res) return res;
      return 0;
}
char const * Statement::getColText(int idx) {
     return (char const *)sqlite3_column_text(stmt, idx);
}

Here is my main app.cpp file

#include <iostream>
#include <stdio.h>
using namespace std;
/* 
* SQLite3 header file
* for getting Constants for verification of results.
*/
 #include "inc\sqlite3.h"
 #include "SQLite.h"

int main() {
    SQLiteConnection con;
    try {
        if (SQLITE_OK == con.connect(":memory:")) {
            cout << "Connected to DB";
            Statement stmt;
            if (SQLITE_OK == stmt.prepare(con.getConn(), "select 'Hello World'")) {
                while (stmt.step())
                {
                    cout << "\n" << stmt.getColText(0) << "\n";
                }
                stmt.finalize();
            }
        }
        else {
            return 1;
        }
    }
    catch (const exception & e) {
        cout << "Exception..."<< e.what();
    }
    getchar();
    return 0;
}

Started first time in Visual C++ and SQLite3 so the knowledge level is beginner and I also don't know much about Modern C++ and STL ;( will learn soon.. Hoping that brilliant minds will explain me what is happening here and how will I be able to get out from that.

回答1:

read access violation exception.

I dont think this is a C++ exception, it is rather hardware exception caused by the fact that your code tries to access memory it should not. It should be generated with additional information like address which might give some hints on the cause of the problem.

How to handle this exception

well, you dont :-) or rather you can't, your app must crash. You might actually write exception handler which could write stack trace to some log file, or make a dump file for later analysis. In large application programmers add lots of logging to at least allow testers to send them log files which might help in finding what application was doing when crash happend.

and what changes i should make in my small wrapper so i can use it in multiple modules of the app.

hard to tell because you should use debugger to find a place when it crashes. Maybe you are using some uninitialized memory, or wrongly using API. Your select statement looks strange, is it correct? But probably it should not crash application. Your destructor looks also suspicious, sqlite3_close(conn); is called even if conn is NULL.



回答2:

If this is related to your other question where you say you tried getting values even when SQLite returns SQLITE_DONE then that is the answer. With that code the stepping has finished and there is nothing to read so reading anyway may cause nasty crashes. You may only read with the code SQLITE_ROW.

Your code returns true on step even when stepping is finished, remove that from the code.