2017-09-29 57 views
-1

我有內存泄漏檢測器的工具,它告訴我下面代碼正在泄漏100個字節由strcpy設置的釋放char *上的內存泄漏?

#include <string> 
#include <iostream> 

void setStr(char ** strToSet) 
{ 
    strcpy(*strToSet, "something!"); 
} 

void str(std::string& s) 
{ 
    char* a = new char[100](); 
    setStr(&a); 
    s = a; 
    delete[] a; 
} 

int main() 
{ 
    std::string s1; 
    str(s1); 
    std::cout << s1 << "\n"; 

    return 0; 
} 

根據this點編號3是漏水的"something!"(10)予分配的量(100)減去長度和我應該泄漏90個字節。

我在這裏丟失了什麼東西,或者安全地假定該工具報錯?

編輯:setStr()是在一個庫中,我看不到代碼,所以我猜想它是這樣做的。它可能是它在堆上分配"something!",那麼情況如何?我們會有90字節泄漏還是100?

+0

隨着代碼顯示你沒有內存泄漏。 –

+0

此外,您要麼泄漏*全部*或分配,或*無*。您不能泄漏部分分配。 –

+0

爲什麼'SetStr'不採用'char *'? – patatahooligan

回答

3

此代碼不會泄漏,並且與第3點不同,因爲您從不覆蓋存儲分配內存指針的變量。這個代碼的潛在問題是它容易受緩衝區溢出的影響,就好像setStr打印超過99個符號,它不是異常安全的,就好像s = a;拋出然後delete[] a;不會被調用並且內存會泄漏。

更新:如果setStr分配新字符串並覆蓋初始指針值,則指向您分配的100字節緩衝區的指針將丟失,並且這100個字節會泄漏。在將其傳遞到setStr之前,您應該初始化anullptr,並在setStr返回後檢查它是否爲空,以便分配s = a;不會導致空指針取消引用。

+0

'setStr()'在庫中,我看不到代碼,所以我猜想它是這樣做的。如果'serStr()'在堆上分配字符串''something!'',它會像點3嗎? – Griffin

+3

@Griffin如果'setStr'是一個庫函數,這是非常關鍵的信息,應該在問題主體中,因爲它改變了一切。很可能''setStr'函數是一個C函數,它模擬傳遞引用並實際爲其內部的字符串分配內存。這意味着如果你自己分配內存,你會*發生內存泄漏。你應該仔細看看這個'setStr'函數的文檔,因爲它應該提及它。 –

+0

@Griffin此外,如果它是一個C函數,那麼它將使用'malloc'(或類似的)而不是'new []'來分配內存。這意味着你不能使用delete []來釋放內存,而應該使用['std :: free'](http://en.cppreference.com/w/cpp/memory/c/free) 。 –

1

總結所有評論,很明顯是什麼問題。您正在使用的庫正在請求char **。這是C函數的一個通用接口模式,它分配內存並返回指向該內存的指針,或者返回指向它們擁有的內存的指針。

您正在泄漏的內存分配在行char* a = new char[100]();。由於setStr正在更改a的值,因此不能再取消分配該內存。

不幸的是,沒有文檔,我們不能推斷出你應該用指針做什麼。

  • 如果它是從一個電話new[]你需要調用delete[]

  • 如果是從打電話到malloc您需要致電std::free

  • 如果它是一個指向庫所擁有的內存的指針,那麼你應該什麼都不做。

您需要查找相關文檔。但是,如果它不可用,您可以在刪除new語句後嘗試使用內存泄漏檢測工具,並查看它是否檢測到泄漏。我不確定從庫函數分配的內存是否可靠,但值得一試。

最後,關於你編輯中的問題,如果你泄漏了內存,你會泄露所有的內容,除非你做了一些未定義的行爲,這是毫無意義的討論。如果您在其上寫入一些數據,那麼這不會改變泄漏的內存量。它仍然是100 * sizeof(char)

+0

'setStr'不會改變'a'的值(好吧,不是在OP發佈的代碼中) –

+0

我知道,但這不是實際運行的代碼.OP澄清了這一點,但忽略了從他的問題中刪除代碼。查看他們的編輯。 – patatahooligan