结构sqlite3的sqlite3c++正向声明导致析构函数中删除时出现无效指针错误

sqlite3 c++ forward declaration of struct sqlite3 leads to invalid pointer error on delete in destructor

本文关键字:删除 错误 指针 无效 析构函数 sqlite3c++ sqlite3 声明 结构      更新时间:2023-10-16

在Linux上使用Eclipse CDT。以下是编译期间的代码和警告:

 #ifndef DATABASECONNECTION_HPP_
#define DATABASECONNECTION_HPP_
#include <sqlite3.h>
#include <string>
using namespace std;
class DatabaseConnection
{
private:
    sqlite3 *_database;
public:
    // constructors
    DatabaseConnection(const string &databaseURI, char mode='w');
    // destructor
    ~DatabaseConnection();
};
#endif /* DATABASECONNECTION_HPP_ */

/*
 * DatabaseConnection.cpp
 *
 *  Created on: Mar 31, 2015
 *      Author: Michael Wilson (mnw380@gmail.com)
 */
#include <DatabaseConnection.hpp>
#include <Exception.hpp>
#include <sqlite3.h>
#include <stdlib.h>
#include <sstream>
#include <FormattedString.hpp>
#include <FileUtils.hpp>
using namespace std;
DatabaseConnection::DatabaseConnection(const string &databaseURI, char mode)
{
   if (mode != 'w' && mode != 'r')
        throw Exception("Exception DatabaseConnection::DatabaseConnection. Mode must be 'r' or 'w' for read/write connection mode");
    int flags = (mode == 'w') ? SQLITE_OPEN_READWRITE : SQLITE_OPEN_READONLY;
    // this enables opening databases using URI
    flags |= SQLITE_OPEN_URI;
    // verify the database URI is formed correctly
    if ( !FormattedString::isFormatted(databaseURI, "file:/.*") && !FormattedString::isFormatted(databaseURI, "http:/.*") ) {
        // if not formed using standard URI syntax, then assume a file path and verify it exists
        if ( !FileUtils::Exists(databaseURI) )
            throw Exception("Exception DatabaseConnection::DatabaseConnection. File does not exist: " + databaseURI);
    }

    // returns non-zero on open error
    if ( sqlite3_open_v2(databaseURI.c_str(), &_database, flags, NULL) ) {
        ostringstream ss;
        ss << "Exception DatabaseConnection::DatabaseConnection. Error opening database " << databaseURI;
        throw Exception(ss.str());
    }
}
DatabaseConnection::~DatabaseConnection()
{
    sqlite3_close(_database);
    delete _database;
}

以及编译期间的警告

g++ -I/opt/ros/indigo/include -I"/home/user/workspace/Project/include" -O0 -g3 -Wall -c -fmessage-length=0 -std=gnu++11 -MMD -MP -MF"src/DatabaseConnection.d" -MT"src/DatabaseConnection.d" -o "src/DatabaseConnection.o" "../src/DatabaseConnection.cpp"
../src/DatabaseConnection.cpp: In destructor ‘DatabaseConnection::~DatabaseConnection()’:
../src/DatabaseConnection.cpp:48:9: warning: possible problem detected in invocation of delete operator: [enabled by default]
  delete _database;
         ^
../src/DatabaseConnection.cpp:48:9: warning: invalid use of incomplete type ‘struct sqlite3’ [enabled by default]
In file included from /home/user/workspace/Project/include/DatabaseConnection.hpp:11:0,
                 from ../src/DatabaseConnection.cpp:8:
/usr/include/sqlite3.h:228:16: warning: forward declaration of ‘struct sqlite3’ [enabled by default]
 typedef struct sqlite3 sqlite3;
                ^
../src/DatabaseConnection.cpp:48:9: note: neither the destructor nor the class-specific operator delete will be called, even if they are declared when the class is defined
  delete _database;

这种方法与此人的做法非常相似http://www.dreamincode.net/forums/topic/122300-sqlite-in-c/

但我想确保释放数据库指针"struct-sqlite3"类成员

您的代码正试图发出delete _database;,其中_database的类型为sqlite3。问题是编译器不知道sqlite3是什么

您正向声明了sqlite3是什么,但要发出delete调用,需要编译了解sqlite3的完整定义。您没有提供此类型的完整定义。

这来自sqlite3 API:https://www.sqlite.org/c3ref/close.html

sqlite3_close()和sqlite3_close_v2()例程是sqlite3对象的析构函数。如果sqlite3对象被成功销毁并且所有关联的资源都被释放,那么对sqlite3_close()和sqlite3_close_v2()的调用将返回SQLITE_OK。