【问题标题】:Pointer Changes Address指针改变地址
【发布时间】:2018-03-18 17:53:52
【问题描述】:

我一直在创建一个与本地 SQLite 数据库交互的 C++ 桌面应用程序。我正在使用存储库模式并将从数据库中检索到的数据存储在类的实例中(用作数据模型)。我已经在我的应用程序的其他地方实现了这种模式,并且一切正常。然而,在这个特定的实现中,类实例(数据模型)的地址似乎在构造和销毁之间发生了变化。

这是我的代码设置示例,使用我在调试执行期间记录的内存地址...

存储库类 - 构造函数:

目前,我让这个存储库类保持对Configs 数据模型类的控制。这在未来可能会改变,但我目前的想法是为了便于构造和销毁这个对象(或者我是这么认为的!)。

ConfigsRepo::ConfigsRepo()
{
    this->_configs = new Models::Configs(); // Memory address: 0x039089e8
}

Repository 类 - Getter 方法:

我省略了数据库连接和 SQL 语句字符串,因为它们可以工作并且不是问题的一部分。

Models::Configs& ConfigsRepo::Get()
{
    int rc = sqlite3_exec("..", "..", &Sql::Convert, &this->_configs, NULL);

    // Check rc == SQLITE_OK, blah blah...

    return *this->_configs;  // Memory address: 0x03908901
}

Sql::Convert 方法:

数据库表中目前只有一行一列。数据检索良好。

int Sql::Convert(void* ret, int count, char** data, char** columns)
{
    // "ret" is a reference to the "Configs" class instance passed
    // by the repository.

    // Memory address of "ret": 0x03918930 - most likely different
    // due to passing by reference.

    // Converting retrieved data to a bool and assigning to a
    // property of the referenced "Configs" class.
    // (if cell equals 1 then 'true', else 'false')
    (*(Models::Configs*)ret).SomeProp = atoi(data[0]) == 1;

    return 0;
}

存储库类 - 析构函数:

ConfigsRepo::~ConfigsRepo()
{
    delete this->_configs; // Memory address: 0x03908901 - exception thrown
    this->_configs = NULL;
}

如你所见,“Configs”对象的内存地址在Sql::Convert回调方法之后发生了变化。销毁ConfigsRepo 类(我尝试在其中delete this->_configs)时,抛出异常:Invalid address specified to RtlValidateHeap

我不确定为什么内存地址似乎发生了变化,我也看不到问题。

注意:我开始相信以这种方式调用delete 并不是设计模式的好习惯,我将在以后重构我的代码。我现在只需要它工作。 :)

提前致谢!

【问题讨论】:

    标签: c++ pointers sqlite


    【解决方案1】:

    查看sqlite3_exe(...) 上的 sqlite3 文档:

    sqlite3_exec() 的第四个参数被传递到每个回调调用的第一个参数。

    所以,关于你的功能:

    int rc = sqlite3_exec("..", "..", &Sql::Convert, &this->_configs, NULL);
    

    您实际上是在传递一个指针指针,即 this->configs 的地址,它本身就是 Models::Configs 的指针

    在回调站点,您将其称为:

    (*(Models::Configs*)ret).SomeProp = atoi(data[0]) == 1;
    

    这是一种复杂的说法:

    (Models::Configs*)ret->SomeProp = atoi(data[0]) == 1;
    

    您可以看到,您并没有撤消您在呼叫站点所做的事情。

    所以,我建议你也改变你的sqlite3_exec()

    int rc = sqlite3_exec("..", "..", &Sql::Convert, this->_configs, NULL);
                                                     ^^^^^^^^^^^^^^
    

    旁白:您不需要将Sql::Convert 传递为&Sql::Convert,就像Sql::Convert 一样

    【讨论】:

    • 你是对的;我不需要传递 _configs 作为参考 - 只需省略与号(“&”) - 仅此一项就解决了问题!我只能将我的转换方法体简化为 ((Models::AppConfigs*)ret)->SomeProp .... 否则我会得到编译错误。
    猜你喜欢
    • 2016-05-26
    • 1970-01-01
    • 2021-12-29
    • 2020-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-12
    相关资源
    最近更新 更多