2013-05-13 64 views
-1

我正在調整大小和對象數組。我做了一個臨時對象,但是當我不刪除它時,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

回答

1

事實上,你可以不在那裏刪除它,因爲你已經將其分配給objarray供以後使用。

最有可能的,你沒有刪除在析構函數objarray;或者其他一些函數重新分配它而不先刪除舊數組。

我會用std::vector而非手工製作的陣列,照顧釋放的我。

+0

謝謝。正如你(和其他人)所建議的那樣,我忽略正確使用析構函數。 – mcallinder 2013-05-14 02:17:58

0

明確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

0

如果這是第二次(或更高版本),你叫resize時間,那麼這是一個非常可能的情況,因爲你正在試圖delete上已經產生了double delete因爲temp已經刪除了一堆,現在你所有的objArray寫入已經進入了一堆屬於堆管理的內存,而不是你的代碼。

各種其他潛在的問題也可能發生在這裏,例如內存現在被用於一些OTHER對象,並且它將事物寫入堆內存中,然後將其用作objArray。

,你正在嘗試做的,所以你不應該刪除temp。不要。