无法删除临时对象

问题描述:

我正在调整大小和对象数组。我做了一个临时对象,但是当我不删除它时,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) 

我认为删除它是不好的,因为它应该让指针悬空,所以我不会感到惊讶的是我得到了段错误。但是,为什么会造成内存问题呢?任何想法将不胜感激。

+4

为什么你会删除'temp'? **你不应该**。删除不释放指针,但指向它。如果你删除'temp',你也会删除你的'objarray'(*它指向*)。 – stardust 2013-05-13 17:05:27

+0

是的,我意识到这一点。我想知道的是为什么它仍然会造成内存问题? – mcallinder 2013-05-13 17:07:48

+0

段错误可能是由其他内容引起的。你会在那里看到效果。但原因可能是在... – stardust 2013-05-13 17:09:21

事实上,你可以不在那里删除它,因为你已经将其分配给objarray供以后使用。

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

我会用std::vector而非手工制作的阵列,照顾释放的我。

+0

谢谢。正如你(和其他人)所建议的那样,我忽略正确使用析构函数。 – mcallinder 2013-05-14 02:17:58

明确delete(或delete[])应该只需要非常低级别的库代码。其他地方你应该使用智能指针。

这里有一个更好的方法是(IMO)更容易理解:

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[]>)都留有一个有效的缓冲区。

+0

使用'std :: unique_ptr'可能是最简单的解决方案,但我不认为'交换“将起作用; “swap”的两个参数必须具有相同的类型。 (当然,一般情况下,他基本上是重新实现了'std :: vector',并且在一般情况下正确执行了这个操作 - 例如,如果'Obj'不支持默认构造,那么这就不重要了。) – 2013-05-13 17:16:10

+0

@James:自然'objarray'也应该是'unique_ptr '......它没有理由成为一个原始指针。 – 2013-05-13 17:16:53

+0

@Sarien:它只是交换指针。因此,现在'temp'拥有需要销毁的旧缓冲区,并且当它在'resize'的大括号处超出范围时就会这样做。 – 2013-05-13 17:19:01

如果这是第二次(或更高版本),你叫resize时间,那么这是一个非常可能的情况,因为你正在试图delete上已经产生了double delete因为temp已经删除了一堆,现在你所有的objArray写入已经进入了一堆属于堆管理的内存,而不是你的代码。

各种其他潜在的问题也可能发生在这里,例如内存现在被用于一些OTHER对象,并且它将事物写入堆内存中,然后将其用作objArray。

,你正在尝试做的,所以你不应该删除temp。不要。