【问题标题】:invalid pointer error when delete[] after c-string has been reallocated by function函数重新分配c字符串后delete []时出现无效指针错误
【发布时间】:2019-01-17 14:27:52
【问题描述】:

我正在尝试使用“new char[]”删除[] 之前由另一个函数分配的 c 字符串 (char*)。但是我得到一个无效的指针错误。

首先是代码

类:

class myclass
{
    public:
        myclass(const char*);
        ~myclass();
        char* getNum(const char*, myclass*);
    private:
        sqlite3* db; //db object
        int rc; //int returned by sqlite3 functions
        char* zErrMsg; //error message
        char* sql; //sql statement
        char* num;                 //<- this is it
        static int callback(void*, int, char**, char**);
};

一些功能:

myclass::myclass(const char* filename)
{
    //allocating  
    num = new char[2];
    num[0] = 'i';
    num[1] = '\0';
    //connect to sqlite db using filename
}

char* myclass::getNum(const char* id, myclass* obj) //obj will be passed to callback function
{
    std::cout<<"getNum"<<std::endl;
    std::cout<<static_cast<void *>(&num[0])<<"("<<num[0]<<")"<<std::endl; //test1. writes address and first char. all seems ok
    delete[] num; //here is the problem
    num = new char[10];
    strcpy(num, "not found");
    std::cout<<static_cast<void *>(&num[0])<<"("<<num[0]<<")"<<std::endl; //test2. writes same address as test1 and first char. all seems ok
    //sql query construction. Nothing wrong here.
    //next query gets executed and callback function gets called.
    rc = sqlite3_exec(db, query, callback, static_cast<void*>(obj), &zErrMsg);
    return num; //returns num from db. "not found" otherwise
}

int myclass::callback(void* obj, int argc, char** argv, char** azColName)
{
    std::cout<<"callback"<<std::endl;
    myclass* const object = static_cast<myclass*>(obj);
    std::cout<<static_cast<void *>(&object->num[0])<<"("<<object->num[0]<<")"<<std::endl; //test3. writes same address as test2 and first char. all seems ok
    delete[] object->num; //no problems here
    object->num = new char[strlen(argv[0])+1]; //address of num changes
    object->num = argv[0];
    std::cout<<static_cast<void *>(&object->num[0])<<"("<<object->num[0]<<")"<<std::endl; //test4. writes different address and first char. But all seems ok.
    return 0;
}

关于回调:似乎 sqlite3_exec() 想要一个静态回调函数。所以它看不到“myclass”的“num”成员,因为它不是静态的。而且我不能使它成为静态的,因为我需要它用于其他成员函数。所以我将对象地址传递给 in 并使用 -> 来访问它的成员。

主要:

int main(int argc, char const *argv[])
{
    myclass a(filename);
    a.getNum("id", &a) //works first time
    a.getNum("id", &a) //doesn't work
    return 0;
}

第一次调用 getNum() 可以完成工作。没有什么不对。 第二个(第一次回调修改num后)我得到一个无效的指针错误。

它发生在 getNum 函数内的第一个 delete[] 上。如果我尝试在它之前输出 num - 一切正常并且我得到正确的输出。

我知道这与回调函数内部的重新分配有关,但我不明白是什么。我必须动态重新分配它,因为我不知道从 db 返回的值的长度。 我在 getNum 中取消分配它,因为我不想要任何内存泄漏。 如果我删除该释放(在 getNum 内),程序似乎可以完美运行(但可能存在内存泄漏?)。

【问题讨论】:

  • 不要使用指针和你自己的内存管理。对于字符串,使用std::string
  • 您在getNum 中获得了字符串复制权,但在callback 中没有;你正在尝试delete[] 一些你没有从new[] 得到的东西。 (当然,你应该做的是使用std::string,别再担心了。)
  • 至于你现在的问题,是不是在构造函数中初始化指针?否则,指针将未初始化且不确定(并且看似随机)。尝试取消引用未初始化的指针,或将其传递给 delete(或 delete[]),会导致 undefined behavior 和可能的崩溃。
  • 对不起,我忘了把构造函数。编辑了我的问题。是的,我初始化它们。
  • 您不应该将this 作为回调对象传递,而不是让调用者决定吗?可能使用不同的对象似乎是错误的。

标签: c++ pointers memory-management sqlite


【解决方案1】:

在您的回调中,您将 num 从不是通过 new 分配的 sqlite 重新分配给 argv[0]。

object->num = new char[strlen(argv[0])+1]; //address of num changes
object->num = argv[0]; // <--- here

你的意思可能是:

object->num = new char[strlen(argv[0])+1]; //address of num changes
strcpy (object->num, argv[0]);

【讨论】:

  • 另外,OP 很可能打算将 argv[0] 复制到 object->num 中。所以,也许提供代码来做到这一点。 *object->num = argv[0]
【解决方案2】:

object-&gt;num = argv[0]; 你在这里重新分配你的指针。因此,您尝试删除 argv[0]。

【讨论】:

    猜你喜欢
    • 2015-07-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多