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

VC6 讓 new 失敗拋出 std::bad_alloc 異常:標準庫缺陷根因與修正方案

     編輯:VC 教學

標準規定 vs VC6 現狀

  • C++ 標準:new 失敗**必須拋出** std::bad_alloc;
  • 不想要異常可用 new (std::nothrow) 返回 NULL;
  • VC6 `` 宣告了兩版 operator new,分別在 newop.cpp (拋出版) 和 newop2.cpp (nothrow 版);
  • **實測**:new BigClass **不拋出異常**,直接返回 NULL (行為如 nothrow)。

根因深度追蹤

  1. 鏈接順序:VC 鏈接器優先解析 **C++ 標準庫** (libcp*.lib),再解析 C 庫 (libc*.lib);
  2. use_ansi.h 透過 #pragma comment(lib, ...) 自動引入對應版本 C++ 庫;
  3. 關鍵發現:dumpbin /SYMBOLS libcp.lib 顯示 newop.obj **無任何符號定義** (空殼);
  4. 查閱 newop.cpp 原始碼:
    #if !defined(_MSC_EXTENSIONS) ... operator new 實作 ... #endif;
  5. _MSC_EXTENSIONS 宏:/Ze (預設,啟用 MS 擴展) 定義它,**導致實作被編譯器剔除**;
  6. VC6 建置標準庫時使用 /Ze,故 newop.obj 空無一物;
  7. 鏈接器轉而解析 **C 庫中的 new.cpp** (非標準、不拋異常、返回 NULL) —— **錯誤符號勝出**。

驗證實驗

#include 
#include 
class BigClass { char buf[0x7FFFFFFF]; };
int main() {
    try { BigClass* p = new BigClass; }
    catch (std::bad_alloc&) { std::cout << "bad_alloc thrown\n"; }
    BigClass* q = new (std::nothrow) BigClass;
    if (!q) std::cout << "nothrow returned NULL\n";
}

**VC6 預設建置輸出**:
nothrow returned NULL (第一個 new 也返回 NULL,無異常)。

修正方案:自行編譯修正版 newop.obj

  1. 複製 VC98\CRT\SRC\newop.cpp、dbgint.h 到專案目錄;
  2. 修改 newop.cpp:#include "dbgint.h" (本地路徑);
  3. 編譯:
    cl /c /Za /D_CRTBLD newop.cpp
    /Za:禁用 MS 擴展 → _MSC_EXTENSIONS 未定義 → 實作生效;
    /D_CRTBLD:繞過 dbgint.h 內部頭文件保護;
  4. 編譯主程式:cl /c /GX test.cpp (/GX 啟用異常處理);
  5. 鏈接:link test.obj newop.obj (新 obj 覆蓋庫中空殼)。

修正後輸出

bad_alloc thrown
nothrow returned NULL
bad_alloc thrown

VC7.1 (VS2003) 已修正

  • 移除 #if !defined(_MSC_EXTENSIONS) 守衛;
  • newop.cpp/newaop.cpp (array new) 實作完整保留;
  • nothrow 版獨立為 newopnt.cpp/newaopnt.cpp。

工程建議

  • **維護 VC6 專案**:專案中加入修正版 newop.cpp (以 /Za 編譯) 或全域關閉優化 (/Od) 並啟用 /GX;
  • **新專案**:**強烈建議遷移至 VS2017+**,完整支援 C++11/14/17/20、標準庫正確、診斷工具豐富;
  • 若必須留 VC6:全代碼審查 new 使用處,**統一改用 new (std::nothrow) + NULL 檢查**,避免假象。
    (或自訂 set_new_handler 模擬異常行為,但不標準。)

後記

作者 2001 年遇此問題,CSDN 發帖無解,擱置 4 年。後因研究 LNK2005 符號重複錯誤,洞悉鏈接器解析規則,重拾舊謎順藤摸瓜,終破案。**原始碼之前,了無秘密。**

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