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

VC6.0 new 運算子失敗不拋出 bad_alloc 異常的原因與解決

     編輯:VC 教學

標準行為

C++ 標準規定 new 失敗拋出 std::bad_alloc;不想拋出用 new (std::nothrow) 回傳 nullptr。

VC6 實作缺陷

VC6 CRT 有兩組 operator new:

  • newop.cpp (C++ 庫):**標準版**,含 throw(std::bad_alloc),連結入 libcp*.lib / msvcprt.lib。
  • new.cpp (C 庫):**非標準版**,void* operator new(unsigned int) **無異常規範**,連結入 libc*.lib。

由於 use_ansi.h 透過 #pragma comment(lib, ...) 強制連結 C++ 庫,但 **連結器解析順序優先搜尋 C 庫**,導致實際調用的是 C 庫版 operator new,**不拋出異常**,直接回傳 NULL (或呼叫 _new_handler 循環)。

驗證代碼

#include 
#include 
using namespace std;

class Huge { char buf[0x7FFFFFFF]; }; // 2GB 必失敗

int main() {
    try {
        Huge* p = new Huge;
        cout << "Unexpected success\n";
    } catch (bad_alloc&) {
        cout << "Caught bad_alloc - CORRECT\n";
    }

    Huge* q = new (nothrow) Huge;
    if (!q) cout << "nothrow returned NULL - OK\n";
}

VC6 Debug/Release 皆輸出:nothrow returned NULL,**無 bad_alloc 被捕獲**。

解決方案

  1. 手動設定 new_handler (最簡單):
    void MyNewHandler() { throw bad_alloc(); }
    int main() {
        _set_new_handler(MyNewHandler); // CRT 全域
        // 之後 new 失敗將拋出 bad_alloc
    }
  2. 強制連結 C++ 庫版 operator new:專案設定 → Link → Ignore Specific Library 加入 libc.lib;libcmt.lib;msvcrt.lib (視配置),但極易引發其他 CRT 符號衝突,**不推薦**。
  3. 升級編譯器:VS2005+ 已修正此行為,符合標準。

最佳實踐

  • VC6 專案**務必在程式啟動早期呼叫 _set_new_handler** 設定拋出 bad_alloc 的處理函數。
  • 代碼中**統一使用 new (nothrow) 並檢查回傳值**,避免依賴異常機制 (VC6 不可靠)。
  • 避免直接包含 <new> 以為即符合標準,**必須實測驗證**。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved