首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> VC >> VC 教學

VC++ 6.0 Debug 版 new/malloc 長時間運行崩潰 Bug 分析與修復

     編輯:VC 教學

現象描述

VC++ 6.0 Debug 版程式若頻繁呼叫 new 或 malloc,運行 4-5 小時後會崩潰,錯誤碼 0x80000003 (Breakpoint),堆疊指向 _heap_alloc_dbg 內的 _CrtDbgBreak()。Release 版與 VS.NET 以上版本不受影響。

根本原因

CRT Debug Heap 內部維護一個 static long _lRequestCurr 計數器 (初始 1),每次配置記憶體遞增。當計數器從 2,147,483,647 (LONG_MAX) 溢位變為 -2,147,483,648 (LONG_MIN),並持續遞增至 -1 時,恰好等於全域變數 _crtBreakAlloc (預設 -1),觸發 _CrtDbgBreak() 中斷程式。

相關原始碼片段 (dbgheap.c):

long lRequest = _lRequestCurr++; // 每次配置遞增
if (lRequest == _crtBreakAlloc)  // _crtBreakAlloc 預設 -1
    _CrtDbgBreak();              // 觸發中斷

解決方案

將 _crtBreakAlloc 設定為極大或極小值,使其永遠不等於 _lRequestCurr。在程式啟動早期 (如 CWinApp::InitInstance) 執行:

#include <limits.h>

long lRequest;
_CrtIsMemoryBlock(malloc(10), 10, &lRequest, NULL, NULL); // 取得目前計數器值
free(...);

long NewCrtBreakAlloc = (lRequest > -1) ? (LONG_MIN / 2) : (LONG_MAX / 2);
_CrtSetBreakAlloc(NewCrtBreakAlloc);

此法確保 _crtBreakAlloc 與遞增計數器永不相遇,徹底解決長時間運行崩潰問題。

補充說明

  • 此 Bug 存在於所有 VC++ 6.0 版本 (含 SP6)。
  • VS.NET (2002) 及後續版本已修正此邏輯。
  • 若專案極度依賴大量動態記憶體配置,升級編譯器為根治之道。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved