VS偵錯工具_ASSERTE(_CrtIsValidHeapPointer(pUserData))崩潰的原因以及解決方案

來源:互聯網
上載者:User

標籤:

偵錯工具,對動態申請的記憶體用free或者delete釋放時程式崩潰,跳出如下對話方塊:


點擊重試,定位到具體的CRT源碼部分:_ASSERTE(_CrtIsValidHeapPointer(pUserData));

1、原因分析:

查看CRT源碼,一步一步看看裡面都幹了什麼吧: _CrtIsValidHeapPointer----->_CrtIsValidPointer---->HeapValidate

首先在_CrtIsValidPointer中檢測這個指標是否有效,即不為空白;然後調用WIndows API  HeapValidate,這個才是關鍵了,CRT 代碼中C++的樂網new 調用的是C語言的malloc,delete調用的是C語言的free。由於C庫函數是跨平台的,那麼CRT的意義就在於在Windows平台上封裝WIN API 來實現這些功能。

HeapValidate功能是檢測一個記憶體指標是否是在這個堆棧上面申請的。每個PE檔案在載入時都會初始化CRT運行庫,調用heapinit.c 中的_heap_init,_heap_init中還是用的WIN API HeapCreate初始化堆棧,然後把這個堆棧的控制代碼儲存到一個全域變數中,後續這個進程在堆棧上申請釋放記憶體都要用到這個控制代碼。上面的崩潰原因就是因為釋放記憶體的指標不是在該PE檔案的堆棧上申請的。

具體說,我的問題其實就是在DLL中申請了一塊記憶體,在EXE中刪除這塊記憶體。但是這兩個PE(exe、dll都是PE檔案)在初始化時分配的堆棧控制代碼是不一樣的,所以就出錯了。

2、解決方案:

問題原因清楚了,其實就是要我們注意,在誰的堆棧上分配的記憶體,就在誰的堆棧上釋放。

方案一:在DLL裡面申請的記憶體,就在DLL裡面釋放,不要由其他模組去釋放;(為了區分第二條,這個前提是exe 和 dll都使用mtd方式編譯)

方案二:讓所有的PE共用一個堆棧控制代碼,所有的模組都採用的mdd方式編譯;

(上面說的是Debug選項下),原因在於,採用mdd編譯時間,所有的模組都會共用同一個msvcr*.dll,堆棧控制代碼作為靜態變數儲存在裡面,所以所有的模組都是同一個堆棧上申請、釋放記憶體,不管哪個模組都可以釋放其他模組申請的記憶體了。而採用mtd編譯時間,所有模組都相當於有自己獨立的一個mscvr*.dll(相當於把msvcr*.dll中需要的代碼都打包到自己裡面去了),因此每個模組在載入的時候都有自己獨立的堆棧,這時去刪除其他模組申請的記憶體,堆棧檢測該指標肯定就是無效的了。

3、後記

碼字好累,語文學的不好,說的有點繞。希望對遇到該問題的人有所協助,謝謝。

VS偵錯工具_ASSERTE(_CrtIsValidHeapPointer(pUserData))崩潰的原因以及解決方案

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.