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

VC6 使用 STL 警示:記憶體配置失敗導致應用程式崩潰

     編輯:關於VC++

問題背景

VC6 預設 operator new 失敗傳回 NULL,但 C++ 標準要求拋出 std::bad_alloc。STL 內部假設 new 會拋出異常,若實際傳回 NULL,會導致未定義行為(如存取 0x1 位址),使應用程式崩潰。

各版本行為差異

環境new 失敗行為
VC6 非 MFC傳回 NULL
VC6 + MFC拋出 CMemoryException
VC.NET (7.0/7.1) 非 MFC拋出 std::bad_alloc (標準)
VC.NET + MFC拋出 CMemoryException (非標準型別)

唯有 VC.NET 非 MFC 專案符合標準,STL 能正確捕捉 bad_alloc。

實際崩潰案例

std::string 建構時呼叫 allocator::allocate → operator new。若傳回 NULL,後續 _Ptr = _S + 1 變為 0x1,隨後 _Refcnt(_Ptr) = 0 解參考 0x0 → 存取違規。

修正方案

  1. 安裝 new-handler:在專案加入 NewHandler.cpp,於 _set_new_handler 註冊處理函數,失敗時拋出 std::bad_alloc。勿使用 _set_new_mode(1)(會影響 malloc 及 new(nothrow))。
  2. 修正 operator new(nothrow):VC6 Release 建置下優化會移除 try/catch,導致 new(nothrow) 仍拋出異常。需自行實作傳回 NULL 的版本,但注意:若連結 DLL CRT,會影響同一進程內所有模組。
  3. 替代 STL 實作:如 STLPort 未使用 new(nothrow),可規避問題。

總結

VC6 非 MFC 專案使用 STL 時,必須 安裝 new-handler 將 new 失敗轉為標準異常,否則記憶體不足時極大機率崩潰。VC.NET 已修正此問題。MFC 專案視 STL 實作而定(多用 catch(...) 較安全)。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved