程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 關於VC 6.0的new調用在debug模式下的bug

關於VC 6.0的new調用在debug模式下的bug

編輯:關於C語言

    維護的項目是用VC6.0開發的,安裝到現場運行發現每個月都要崩潰一次,經過檢查dmp文件發現是由VC6.0的crt庫中new操作所對應的代碼引起Microsoft visual Studio/VC98/Crt/Src/dbgheap.c),這個文件中_heap_alloc_dbg()函數用到一個long型的變量用來計數,一旦該計數器到達long型的最大值就會引發int 3中斷《VC++6.0之new調用的bug》:

  1. /* break into debugger at specific memory allocation */ 
  2.         if (lRequest == _crtBreakAlloc) 
  3.             _CrtDbgBreak(); 

    這個問題其實很容易解決,經查詢vs2003已經修改為這樣,已經消除了這個bug:

  1. /* break into debugger at specific memory allocation */ 
  2.         if (_crtBreakAlloc != -1L && lRequest == _crtBreakAlloc) 
  3.             _CrtDbgBreak(); 

    從邏輯上消除這個bug很容易,但問題是這個是MFC的庫,到網上查詢解決辦法,有以下幾種方案:

    1、用UE打開msvcrtd.dll,使用16進制編輯模式,查找得到的二進制指令,發現確實只有二處,把緊接著它們的0xCC替換為0x90,問題解決

    2、修改debug report模式,即用_CrtSetReportMode和_CrtSetReportFile將_CrtDbgBreak彈出的對話框屏蔽掉,代碼如下:

  1. _CrtSetReportMode( _CRT_ASSERT, _CRTDBG_MODE_FILE ); 
  2. _CrtSetReportFile( _CRT_ASSERT, _CRTDBG_FILE_STDOUT ); 
  3. _CrtSetReportMode( _CRT_ERROR, _CRTDBG_MODE_FILE ); 
  4. _CrtSetReportFile( _CRT_ERROR, _CRTDBG_FILE_STDOUT ); 
  5. _CrtSetReportMode( _CRT_WARN, _CRTDBG_MODE_FILE ); 
  6. _CrtSetReportFile( _CRT_WARN, _CRTDBG_FILE_STDOUT ); 

    3、改用內存池之類的技術,減少new的使用

    4、將項目改為VS2003以上的IDE去編譯

    首先試著用UE編輯這個dll,發現自己這方面知識太欠缺不知道如何改,問了身邊幾個人也沒明白的,而且這個方案屏蔽了_CrtDbgBreak的功能也可能帶來其他問題,只能放棄。

    滿心歡喜的嘗試第二種方案,卻發現根本屏蔽不了,該彈出照樣彈出,貌似只能截獲一部分,但具體為什麼不能生效也沒搞懂。

    緊接著嘗試了用內存池方式來減少new的使用,使用了boost提供的內存池試了一下還蠻容易上手使用的,不過缺點是這種方法治標不治本,MFC自己還有大量的new操作。

    比較無奈的嘗試了一下用VS2008編譯這套代碼,竟然產生了上千條錯誤,很費勁的改了一天,能編譯出EXE了。拿到運行環境一運行竟然崩潰……

--------------------------------------------------------------------------

    幸好最後找到了解決辦法,那就是本文要隆重介紹的終極解決方案:

    之前一直認為dbgheap.c文件是mfc一部分,不能改寫!偶然發現了其實MFC提供了重編譯它的makefile文件,請參考《重新編譯生成C運行時庫》。

    首先把dbgheap.c文件中bug修改過來,然後按照這篇文章介紹的方法重編譯C運行時庫,就一切OK啦!

    需要注意的是msvcrtd.dll我沒有生成出來,編譯到這裡發生錯誤停止了,但libcmt.lib可以編譯出來,最後我的項目只能使用靜態鏈接方式使用MFC庫。

 

本文出自 “Hello Snow!” 博客,請務必保留此出處http://hellosnow.blog.51cto.com/164899/732143

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved