malloc.c:3096: sYSMALLOc: Assertion `(old_top == ...) failed.
Aborted
程式在 push_back() 呼叫若干次後崩潰,GDB 追蹤進入 malloc.c 內部斷言失敗。初步懷疑記憶體洩漏或堆耗盡,實際卻是結構體記憶體對齊設置未還原導致的堆元資料破壞。
// 錯誤代碼片段
#pragma pack(push, 1) // 關閉對齊,1 位元組對齊
struct MyStruct {
char c;
int i; // 正常應在 4 位元組邊界,現在緊湊排列
// ...
};
// 缺少 #pragma pack(pop) !
#pragma pack(push, 1) 生效範圍延伸至後續所有結構體定義(含標準庫頭檔內部結構)。std::vector、std::string、分配器元資料)被迫 1 位元組對齊,導致其大小/佈局與預期不符。vector::push_back 觸發擴容、分配記憶體時,分配器根據錯誤的大小/對齊要求向 malloc 申請塊。malloc/free 內部一致性檢查失敗,拋出 memory corruption。#pragma pack(push, 1)
struct PackedStruct {
char c;
int i;
};
#pragma pack(pop) // ★ 恢復預設對齊,限制影響範圍
#pragma pack 僅在極少數場景必要(網路協議封包、硬體暫存器映射、二進制檔案格式)。push/pop 包裹單一結構體定義,避免汙染後續代碼。alignas(1) 指定單一結構體對齊,不影響全域:struct alignas(1) Packed { char c; int i; };-Wpadded (GCC/Clang) 可檢測結構體因對齊產生的填充位元組,輔助判斷是否真需要 pack。遇到
malloc內部斷言失敗、free(): invalid pointer、double free等堆錯誤,優先檢查近期修改的結構體定義、#pragma pack、自定義分配器。堆破壞往往在破壞點之後很久才爆發,堆疊追蹤通常指向無辜的受害者(如 vector::push_back),而非真兇。