1. 程式人生 > >Delete出錯分析總結(個人總結很到位) 0x0000007ff64426f87e(ucrtbased.dll)處(處於dataa.exe中)引發的異常:

Delete出錯分析總結(個人總結很到位) 0x0000007ff64426f87e(ucrtbased.dll)處(處於dataa.exe中)引發的異常:

近日在除錯C++程式中new class 後delete 出現如下錯誤:
* 0x0000007ff64426f87e(ucrtbased.dll)處(處於dataa.exe中)引發的異常:0xC0000005:讀取位置(0xffffffffffffffff)時發生訪問衝突。*

bimage *metric=new bimage(image);
xxxx
xxxx
delete metric;

bimage定義:
class bimage{
pubic:
    bimage();
    bimage(bimage*image){allocate_buf();variable assignment;};
    ~bimage();
private
: int xx; uinit32 *buf[4]; // uint32 **p_buf[4]; bool allocate_buf() { buf[0]=new uint32[w*h]; p_buf[0]=new uint32*[h]; } }

因為只用到一個通道,故allocate_buf中只對buf[0] 和p_buf[0]分配了空間。
百度了一下delete出錯的可能性之後,有帖子說
“初始化什麼也沒做,並沒有指向一塊分配的好記憶體”,我猜想這可能是出錯的原因,故改寫allocate_buf

    bool
allocate_buf() { buf[0]=new uint32[w*h]; p_buf[0]=new uint32*[h]; buf[1]=buf[0]; buf[2]=buf[0]; buf[3]=buf[0]; p_buf[1]=p_buf[0]; p_buf[2]=p_buf[0]; p_buf[3]=p_buf[0]; }

執行後出現
0x0000007ff64426f87e(ucrtbased.dll)處(處於dataa.exe中)引發的異常:0xC0000005:讀取位置(0x00321554ddc0e8)時發生訪問衝突。
好傢伙,果然跟未賦值有關。但是依然有訪問錯誤,繼續百度,找到一篇:
”不能重複delete“
buf[1]=buf[0];指標賦值,delete時明細會刪除兩次啊。再改,賦值為NULL總可以吧

    bool allocate_buf()
    {
        buf[0]=new uint32[w*h];
        p_buf[0]=new uint32*[h];
        buf[1]=NULL;
        buf[2]=NULL;
        buf[3]=NULL;
        p_buf[1]=NULL;
        p_buf[2]=NULL;
        p_buf[3]=NULL;
   }
總算順利通過執行。填坑完畢。

參考https://blog.csdn.net/tianxia_taiping/article/details/10928927 總結一下Delete 中的坑
Delete出錯原因分析:
1.陣列首地址被無意更改。例如:int A[10]; A++;
2.作用域不同。例如:在函式A中new的記憶體 int p = new int;在函式B中delete p,此時函式B不認識識別符號p。
3.重複delete。例如:在dll的外部對dll的資源進行delete,有可能dll內部自己做了delete操作,此時會重複delete。
4.new的指標指向不定,未初始化,delete時出錯。
5.記憶體越界。這是最常見的,new的空間太少,使用時超出範圍,更改了不屬於程式自己的地址上的值。如果更改的地址是系統關鍵區域,程式會馬上崩潰;如果是一般的地址,系統不會馬上檢測出來,這樣就埋了一個bug。
例如:VC分配記憶體時,除了本身的資料空間外,還會分配額外的管理記憶體。例如在所分配記憶體的前後會放置邊界識別符號0xfdfdfdfd。若越界操作,改變了邊界外的值,破壞了管理記憶體,delete時會失敗或卡死。如圖所示:0xfdfdfdfd為邊界識別符號,0xcd 0xcd 0xcd為分配的記憶體,堆區分配的記憶體未初始化時,VC填充0xcd。前面的0x00000003為分配的記憶體大小,0x00000001為記憶體分配目的,0x000000ab為分配的記憶體編號

解決方法:
1.當傳入的形參是陣列時,能加const的就加const,防止在函式內部中的意外操作。
2.記憶體new和delete時,原則:誰申請誰釋放。
3.在delete指標後,將指標置為NULL。例如:delete p; p = NULL;
4.對new申請後的指標變數賦值,或者p=NULL;
5.記憶體越界情況太多了,不具體說了。一般情況,在new之後,需要判斷分配記憶體是否成功。宣告指標後,置為NULL,例如:int *p = NULL;