| 特性 | malloc/free | new/delete |
| 性質 | 庫函數 | 運算子 (可重載) |
| 型別安全 | ❌ 返回 void* | ✅ 返回具型別指標 |
| 建構/解構 | ❌ 不調用 | ✅ 自動調用 |
| 失敗處理 | 返回 NULL | 拋出 std::bad_alloc |
| 陣列支援 | 手動計算大小 | new T[n] / delete[] |
| 擴展性 | 難 | 可全域/類別重載 |
致命錯誤:混用導致未定義行為
// 錯誤示範
int* p1 = (int*)malloc(sizeof(int));
delete p1; // UB: free() 期望 malloc 記憶體,delete 期望 new 記憶體
int* p2 = new int;
free(p2); // UB: 反之亦然
鐵律: malloc 配 free,new 配 delete,new[] 配 delete[]。
為何保留 malloc/free?
- C++ 需呼叫 C 庫函數,C 庫內部用
malloc/free。
- 某些底層記憶體操作 (共享記憶體、記憶體映射檔) 需 C API。
- 嵌入式環境無異常支援時,
new (std::nothrow) 仍可用,但 malloc 更通用。
常見陷阱與解決方案
- 未檢查分配失敗: 使用
if (p == nullptr) 或 try-catch (bad_alloc),或啟用 new (std::nothrow)。
- 未初始化讀取: 啟用
-Wuninitialized、Sanitizer、std::optional 表達可無狀態。
- 野指標/二次釋放: 釋放後立即置
nullptr,改用智慧指標自動管理。
- 記憶體洩漏: RAII 容器/智慧指標、Valgrind/ASan/Dr. Memory 定期檢測。
現代 C++ 記憶體管理鐵三角
// 1. 單一擁有權
std::unique_ptr<Resource> p = std::make_unique<Resource>(args);
// 2. 共享擁有權
std::shared_ptr<Resource> p = std::make_shared<Resource>(args);
// 3. 弱引用 (打破循環)
std::weak_ptr<Resource> wp = p;
99% 場景無需手寫 new/delete。
32/64 位「記憶體耗盡」迷思破解
- 現代 OS 支援虛擬記憶體:物理 RAM 不足時自動換頁至磁碟。
- 32 位進程位址空間 4GB (用戶態通常 2/3GB),地址空間耗盡 遠早於物理記憶體耗盡。
- 64 位進程位址空間 128TB+,實際受限於物理 RAM + 交換檔大小。
- 結論: 檢查
new 返回 nullptr / 捕獲 bad_alloc 仍有意義 (地址空間碎片化、資源配額、嵌入式無交換檔),但不再是「物理 RAM 滿」的同義詞。
- 上一篇文章: C++ 建構函數完全指南:初始化列表、成員初始化順序、委派建構與現代最佳實踐
- 下一篇文章: C++ 語言特性與工程心法:類型安全、命名規範、OOP 本質與大師成長路徑
Copyright ©
程式碼之家 All Rights Reserved