【问题标题】:c++ valgrind double pointer delete for memory leak preventionc ++ valgrind双指针删除用于防止内存泄漏
【发布时间】:2012-11-27 13:33:15
【问题描述】:

阅读后: C++ Array of pointers: delete or delete []? (由 shai vashid 回复) 和 http://www.cplusplus.com/forum/beginner/6651/

我实现了以下:

内核.h

unsigned int **ConfigMeM;
//.....
~Kernel(){ //destructor
    for (unsigned int i=0; i<MeMSize; i++)
        delete [] MeM[i]; //Valgrind:- Invalid read of size 4
                                       - Invalid free() / delete / delete[] / realloc()
    delete [] MeM; //Valgrind: Invalid free() / delete / delete[] / realloc()

    for (unsigned int i=0; i<_item_tot; i++)
        delete [] ConfigMeM[i]; //Valgrind: Same comments as above
    delete [] ConfigMeM; //Valgrind: same as above
};

内核.cpp

//.......
MeM = new unsigned int*[MeMSize];
for (unsigned int i=0; i<MeMSize; i++){
    MeM[i] = new unsigned int[11]; //Valgrind: 14,608 bytes in 332 blocks are definitely lost in loss record 2,021 of 2,036
}
for (unsigned int i=0; i<MeMSize; i++){
    for (int j=0; j<10; j++){
        MeM[i][j] = 0;
    }
}
 //.....
 ConfigMeM = new unsigned int*[_item_tot];
for (unsigned int i=0; i<_item_tot; i++){
    ConfigMeM[i] = new unsigned int[3]; //Valgrind: 1,200 bytes in 100 blocks are definitely lost in loss record 1,131 of 2,036 
}
for (unsigned int i=0; i<_item_tot; i++){
    for (int j=0; j<3; j++){
        ConfigMeM[i][j] = 0;
    }
}
  //.....

我不确定自己做错了什么。

有什么建议吗?

谢谢。

【问题讨论】:

  • 你是否多次运行Kernel.cpp中的代码?
  • Kernel.cpp 中的代码是构造函数的一部分,还是其他?您是否声明了自己的复制构造函数和复制赋值运算符(根据Rule of Three)?我的猜测是你不是,你最终会得到两个试图删除相同内存的对象。
  • @KerrekSB 是的,你是对的!在顶层模块中创建了几个内核副本。例如,在当前示例中为 64。这有什么关系?!
  • “这有什么关系?”想一想:int * p = new int; p = new int; p = new int; delete p;
  • @KerrekSB 我不是故意要挑战你的!!我现在只想问我可以做什么以及如何修改我的代码?

标签: c++ valgrind double-pointer


【解决方案1】:

我最好的猜测是,您的类正在使用隐式生成的复制构造函数或复制赋值运算符复制一个对象。这将留下两个具有指向同一内存的指针的对象;两者都会尝试在销毁时删除此内存,从而导致双重删除错误。

最简单的解决方法是通过删除这些函数来防止复制:

Kernel(Kernel const&) = delete;
void operator=(Kernel const &) = delete;

或者,如果你被一个古老的编译器困住了,把它们声明为私有的,没有函数体。

如果您需要复制这些对象,那么您将需要实现这些对象,也许是为了执行分配新内存块的“深度复制”。

或者,使用std::vector 管理动态数组可能更容易;这已经具有正确的复制语义,并且可以很简单地初始化:

std::vector<std::vector<unsigned int>> MeM, ConfigMem;

(MemSize, std::vector<unsigned int>(11));

【讨论】:

    猜你喜欢
    • 2013-11-30
    • 2018-10-18
    • 1970-01-01
    • 2019-03-31
    • 2020-03-31
    • 2016-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多