C++ 標準規定 new 失敗拋出 std::bad_alloc。但 Visual C++ 6.0 默認返回 NULL,導致 STL 內部假設失效,引發訪問違規崩潰。
| 版本 | 純 C++ new | MFC new |
|---|---|---|
| VC6 | 返回 NULL | 拋 CMemoryException |
| >=VC7.1 | 拋 std::bad_alloc | 拋 CMemoryException |
VC7.1+ 鏈接順序影響行為:標準庫在前拋異常,CRT 在前返回 NULL。可鏈接 thrownew.obj 強制拋異常。
STL string 擴容時 allocator.allocate 調用 new。若返回 NULL,指針運算 ptr+1 得 0x1,隨後寫入導致 Access Violation。正確流程應捕獲異常重試或傳播。
#include
#include
#pragma init_seg(lib)
namespace {
int new_handler(size_t) { throw std::bad_alloc(); return 0; }
struct NewHandler {
NewHandler() { _set_new_handler(new_handler); }
~NewHandler() { _set_new_handler(nullptr); }
} g_NewHandler;
}
包含此代碼後,new 失敗將拋出 std::bad_alloc,STL 行為恢復正常。
new (std::nothrow) 在 VC6 優化下可能導致異常終止,需關閉優化或自行實現。
new_handler 確保拋異常。catch (const std::bad_alloc&) 或 catch (...) (MFC/STL 混用時)。nothrow 版需檢查)。