2009-10-28 169 views
0

你如何解決你從漏洞本身的函數返回的內存泄漏?當您返回泄漏的內存時修復內存泄漏?

例如,我做了一個char* returnMe = new char[24324]; returnMe是從函數返回的結果。你如何解釋這種內存泄漏?一旦它被返回,你如何銷燬它?我有一些內存管理規則,它會在內存泄漏上拋出運行時錯誤來阻止它,所以我無法真正忽略它。

Orrr我是一個傻瓜,這不是泄漏,意味着泄漏在別處?

+0

這只是一個泄漏,如果你沒有參考它,因此沒有是釋放它。 – 2009-10-28 02:24:47

+0

儘管我的例子,它開始作爲一個BYTE數組,並在返回時轉換爲char *,因爲函數返回char *。這可能是原因嗎? – Mark 2009-10-28 02:26:00

+0

@Shhnap:對你的評論精確:如果你從堆棧中引用它。如果兩個元素互相引用,但無法從堆棧訪問,則會泄露... – 2009-10-28 07:25:59

回答

13

這不是一個泄漏,如果你回吧(當然,這不是你的泄漏)。

您需要考慮資源所有權。如果你從你的函數返回一個分配的緩衝區,函數的調用者現在負責它。 API應該明確說明它在完成時需要被釋放。

無論他們自己釋放它還是將它傳遞給另一個函數以釋放它(封裝以防止釋放內存需要做更多工作)是API的另一個問題。

3

指針returnMe仍然可以返回delete[]。這不是內存泄漏,除非您忘記刪除returnMe

+0

嗯......這就是delete [] returnMe。刪除returnMe通常會工作,但實際上並不正確。 – 2009-10-28 02:32:42

+0

對 - 謝謝。改變它刪除[] – 2009-10-28 02:33:47

2

如果你的函數返回一個已分配的緩衝區,那麼就沒有泄漏。更好的是,如果客戶代碼有意識地調用你的例程並且對返回的內容沒有做任何事情,那麼會出現泄漏,但在這種情況下,這是客戶端代碼違反了你的合同。

當緩衝區返回時,它由客戶端代碼控制。一般來說,讓可靠編程讓分配/釋放在同一層發生是一個好主意。這意味着如果你有一個返回緩衝區的例程,你應該有一個相應的例程來釋放它,即使客戶端代碼可以調用delete []。

例如:假設你有這樣的代碼

char *mylib_gimmeh_buffer() { 
    char* returnMe = new char[24324]; 
    return returnMe; 
} 

爲了對稱,你應該也

char *mylib_free_buffer(buffer) { 
    delete[] buffer; 
} 

現在,您的客戶端代碼應該這樣的表現

buf = mylib_gimmeh_buffer(); 
/* do something with buf */ 
mylib_free_buffer(buf); 

如果您客戶端做這樣的事情

mylib_gimmeh_buffer(); // just for fun 

或類似這樣的

buf = mylib_gimmeh_buffer(); 
/* do something with buf */ 
/* never call mylib_free_buffer() */ 

然後有內存泄露

1
char* function() 
{ 
    char* returnMe = new char[24324]; 
    return returnMe; 
} 

int main() 
{ 
    char* pGetReturnME = function(); 
    delete [] pGetReturnME; 
} 

您仍然可以釋放只有當你有一個指向分配內存的函數分配的內存。如果函數返回指向已分配內存的指針,則可以使用deletedelete[]進行釋放。

爲了避免多重刪除或內存泄漏,您必須小心使用明確的內存分配和釋放協議。

+0

請不要'void main()'。請參閱http://www.research.att.com/~bs/bs_faq2.html#void-main – 2009-10-28 02:30:58

+0

謝謝。固定相同。 – 2009-10-28 02:33:21

1

調用函數負責釋放返回的內存。

void function() { 
    char *to_free = NULL; 
    //to_free does not need to be freed yet 

    to_free = function_that_uses_new_to_set_return(); 

    //to_free now must be freed if that function worked 
    if (to_free != NULL) delete[] to_free; 
} 
+0

你當然不想在已經用new分配的指針上調用'free'。你應該編輯這個帖子來將'free'改爲'delete []' – 2009-10-28 02:35:11

1

儘管可能有一個分配內存並返回指針的函數,但它確實很容易出錯......每當有人調用該函數時,他們都需要知道函數將爲其分配內存,並且他們需要知道他們有責任釋放該內存,並且他們需要知道在完成內存釋放時使用的適當方式(delete?delete []?free()?還有其他內容?),以及他們需要確保在任何情況下自由發生一次,並且他們需要確保在自由發生之後不再重新引用指針。

不可避免的是,在一個不平凡的程序中,某個人(可能是你!)會得到其中一個錯誤的東西。然後有人(可能是你)會花費幾個小時的時間與調試器(或者如果你幸運的話,valgrind)追蹤爲什麼你的程序有時會崩潰或泄漏內存。這真的沒有什麼樂趣。

幸運的是,在C++中,有更好的方法來解決這個問題,這對於調用者來說很難實現。例如,您可以返回一個shared_array,而不是返回一個原始指針,它會在最後一個指針消失時自動刪除分配的內存。這樣,沒有人需要考慮內存管理,它「只是有效」。

一旦你習慣了這樣做,你永遠不會想回去!

0

一種解決方法是以難以泄漏的方式返回內存。例如。將其作爲boost::shared_ptr用自定義刪除器返回(因爲您需要刪除[])。現在它實際上需要調用者的努力來泄漏。