c++指針傳遞導(dǎo)致的重復(fù)釋放問題解決
first
先看這段代碼,有多個地方都會釋放 pPointer 的對象空間,但是為了防止重復(fù)釋放,在第二次釋放時做了判空處理;不為空才釋放;
#include <iostream>
using namespace std;
// 釋放內(nèi)存
void release(int *pPointer){
delete pPointer;
pPointer = nullptr;
}
int main() {
int *pPointer = new int();
// 釋放
release(pPointer);
if(pPointer) delete pPointer;
return 0;
}
執(zhí)行結(jié)果如下, 報錯了,告訴我執(zhí)行了2次free函數(shù),也就是重復(fù)釋放了;這是怎么回事呢? 我明明有做判空啊;
free(): double free detected in tcache 2 Process finished with exit code 134
原因
原來;在調(diào)用release函數(shù)時,傳入的指針變量,實際是經(jīng)過了拷貝的;不信是吧,我們來做個實驗,在main函數(shù)和release函數(shù)都打印下 pPointer 對象的地址,代碼如下
void release(int *pPointer){
printf("release pPointer:%x\n",&pPointer); // 打印pPointer指針對象的地址
delete pPointer;
pPointer = nullptr;
}
int main() {
int *pPointer = new int();
printf("main pPointer:%x\n",&pPointer); // // 打印pPointer指針對象的地址
// 釋放
release(pPointer);
if(pPointer)delete pPointer;
return 0;
}
執(zhí)行結(jié)果如下, 可以看到 2個指針地址是不同的,這也就證明了,在傳參的過程中是發(fā)生了拷貝的;release 函數(shù)中的 pPointer 對象和main函數(shù)中的 pPointer 對象并不是同一個對象,只是他們都指向了同一塊內(nèi)存。
main pPointer:f22d1fb0 release pPointer:f22d1f98 free(): double free detected in tcache 2 Process finished with exit code 134
所以,他們的時間線如下:
- 在 release 函數(shù)內(nèi)釋放 pPointer, 并將 pPointer 賦值為 nullptr,此時,pPointer 所指向的內(nèi)存塊已經(jīng)被釋放,
- 但是只是將 release 函數(shù)內(nèi)的 pPointer 變量賦值為 nullptr,main函數(shù)中 pPointer 還是指向原來的地址;因為指針指向的內(nèi)存塊已被釋放,此時 main 函數(shù)中 pPointer 就是個野指針;
- 當(dāng)指執(zhí)行到
if(pPointer) delete pPointer;代碼時,pPointer 并不是空指針 nullptr ,它還指向原來的地址,所以判斷if(pPointer)的結(jié)果為真(true),然后會執(zhí)行delete pPointer;,但是原來地址的空間已經(jīng)在release函數(shù)釋放了,執(zhí)行delete pPointer;后就會報錯:double free detected in tcache 2;
解決
方案一 :使用指針引用
將release函數(shù)的參數(shù)改為指針引用,如下,注意看,*后面多了個&符號,其他代碼無需改動
void release(int *& pPointer){
delete pPointer;
pPointer = nullptr;
}
再次執(zhí)行后,就不會報錯了, 且main函數(shù)和release函數(shù)的 pPointer 對象地址也是相同的
main pPointer:c12d0580 release pPointer:c12d0580 Process finished with exit code 0
方案二:使用二級指針
將release函數(shù)的參數(shù)改為二級指針,也能解決問題,如下
void release(int **pPointer){
printf("release pPointer:%x\n",pPointer);
delete *pPointer; // 這里需要解引用
*pPointer = nullptr; // 這里需要解引用
}
int main() {
int *pPointer = new int();
printf("main pPointer:%x\n",&pPointer);
// 釋放 - 需要加上取地址符號
release(&pPointer);
if(pPointer)delete pPointer;
return 0;
}
執(zhí)行后結(jié)果如下
main pPointer:d2699950
release pPointer:d2699950
Process finished with exit code 0
到此這篇關(guān)于c++指針傳遞導(dǎo)致的重復(fù)釋放問題解決的文章就介紹到這了,更多相關(guān)c++指針傳遞導(dǎo)致重復(fù)釋放內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C++基礎(chǔ)入門教程(一):基礎(chǔ)知識大雜燴
這篇文章主要介紹了C++基礎(chǔ)入門教程(一):基礎(chǔ)知識大雜燴,本文講解了注釋、頭文件、命名空間等內(nèi)容,需要的朋友可以參考下2014-11-11
Cocos2d-x保存用戶游戲數(shù)據(jù)CCUserDefault類使用實例
這篇文章主要介紹了Cocos2d-x保存用戶游戲數(shù)據(jù)CCUserDefault類使用實例,需要的朋友可以參考下2014-09-09
復(fù)數(shù)乘法中的結(jié)構(gòu)體賦值實現(xiàn)代碼
復(fù)數(shù)乘法中的結(jié)構(gòu)體賦值實現(xiàn)代碼。需要的朋友可以過來參考下,希望對大家有所幫助2013-10-10

