无法删除临时对象

时间:2013-05-13 17:03:20

标签: c++ pointers delete-operator

我正在调整对象和对象数组。我做了一个临时对象,但是当我不删除它时,Valgrind显示内存泄漏和错误。删除它会导致段错误。只是想知道Valgrind在抱怨什么......

void Obj::resize()
{
  Obj *temp = new Obj[size * 2];   //<-- line 92
  for (int i = 0; i < size; i++)
    temp[i] = objarray[i];
  delete [] objarray;
  objarray = temp;
  size *= 2;
  //delete temp;   //<-- causes segfault
  //delete [] temp;  // also segfaults, tried them both just in case :\
}

以下是Valgrind报告:

==9292== HEAP SUMMARY:
==9292==     in use at exit: 21,484 bytes in 799 blocks
==9292==   total heap usage: 3,528 allocs, 2,729 frees, 91,789 bytes allocated
==9292==
==9292== 21,484 (2,644 direct, 18,840 indirect) bytes in 1 blocks are definitely lost in loss record 4 of 4
==9292==    at 0x4008409: operator new[](unsigned int) (vg_replace_malloc.c:357)
==9292==    by 0x804AC7E: MyClass::resize() (file.cpp:92)
==9292==    by 0x804AC34: MyClass::add(int, int) (file.cpp:82)
==9292==    by 0x804AAE6: getline(std::istream&, MyClass&) (file.cpp:66)
==9292==    by 0x8049772: main (otherfile.cpp:39)
==9292==
==9292== LEAK SUMMARY:
==9292==    definitely lost: 2,644 bytes in 1 blocks
==9292==    indirectly lost: 18,840 bytes in 798 blocks
==9292==      possibly lost: 0 bytes in 0 blocks
==9292==    still reachable: 0 bytes in 0 blocks
==9292==         suppressed: 0 bytes in 0 blocks
==9292==
==9292== For counts of detected and suppressed errors, rerun with: -v
==9292== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)

我对gdb不是很好,但得到了这个回溯:

    (gdb) run
Starting program: 

Program received signal SIGSEGV, Segmentation fault.
0x46ed40e3 in free () from /lib/libc.so.6
Missing separate debuginfos, use: debuginfo-install glibc-2.15-58.fc17.i686 libgcc-4.7.2-2.fc17.i686 libstdc++-4.7.2-2.fc17.i686
(gdb) backtrace
#0  0x46ed40e3 in free () from /lib/libc.so.6
#1  0x4742dba0 in operator delete(void*) () from /lib/libstdc++.so.6
#2  0x0804ad68 in MyClass::resize (this=0xbffff28c) at file.cpp:98
#3  0x0804ac35 in MyClass::add (this=0xbffff28c, month=10, day=31)
    at file.cpp:82
#4  0x0804aae7 in getline (input=..., a=...) at file.cpp:66
#5  0x08049773 in main (argc=1, argv=0xbffff344) at otherfile.cpp:39
(gdb)

我认为删除它是不好的,因为它应该只是让指针悬空,所以我得到一个段错误并不让我感到惊讶。那么,为什么它会引起记忆问题呢?任何想法都将不胜感激。

3 个答案:

答案 0 :(得分:1)

实际上,您无法将其删除,因为您已将其指定给objarray以供日后使用。

最有可能的是,你没有在析构函数中删除objarray;或者其他一些功能是重新分配它而不先删除旧数组。

我会使用std::vector而不是手工制作的数组来处理我的释放。

答案 1 :(得分:0)

只有在非常低级的库代码中才需要显式delete(或delete[])。其他地方你应该使用智能指针。

这是一种更容易理解的更好的方法:

std::unique_ptr<Obj[]> temp(new Obj[size * 2]);

// copy stuff from objarray to temp

swap(objarray, temp);

就是这样。如果交换成功,unique_ptr析构函数将释放旧的objarray缓冲区。如果在复制期间抛出异常,它将释放新的临时缓冲区。在任何一种情况下,objarray(也应该是std::unique_ptr<Obj[]>)都会留下有效的缓冲区。

答案 2 :(得分:0)

如果这是您调用resize的第二个(或更晚)时间,那么这是一种非常可能的情况,因为您试图在已经拥有{{1}的堆上delete因为double delete已经被删除了,现在所有的temp写入都进入了一堆属于堆管理的内存,而不是你的代码。

此处也可能发生各种其他潜在问题,例如内存现在用于某些OTHER对象,并且它正在将内容写入堆内存,然后将其用作objArray。

您不应删除您尝试执行此操作的objArray。只是不要。