堆內存不自動回收,未釋放導致洩漏,釋放後不歸零導致野指針。商業代碼中結構體常包含指針成員,釋放順序與歸零策略至關重要。
// 錯誤:形參p是副本,無法修改實參指針
void freePointer(void *p) {
if (p != NULL) { free(p); p = NULL; }
}
#define FREE(X) \
do { \
if ((X) != NULL) { \
free((void *)(X)); \
(X) = NULL; \
} \
} while(0)
// 使用:FREE(pRole); // 一行搞定釋放+歸零
void freePointer(void **p) {
if (*p != NULL) {
free(*p);
*p = NULL;
}
}
// 使用:freePointer((void **)&pRole); // 較繁瑣
typedef struct { char *name; } ACT; // 動畫數據
typedef struct { ACT *body; } Role; // 角色含指針成員
// 創建:分配主結構體,再分配成員指針
Role *creatRole(const char *roleName, uint8 weaponId) {
Role *role = (Role *)malloc(sizeof(Role));
role->body = (ACT *)malloc(sizeof(ACT));
// ... 初始化 ...
return role;
}
// 銷毀:遞歸釋放成員指針,最後釋放主體並歸零調用者指針
void destroyRole(Role *role) {
if (role == NULL) return;
destroyAct(role->body); // 先釋放成員指針
free(role); // 再釋放主體
// 注意:此處 role = NULL 無法影響實參!
}
// 調用方必須手動歸零
Role *pRole = creatRole("hero", 0);
destroyRole(pRole);
pRole = NULL; // 關鍵步驟!
項目統一採用 FREE() 宏,制定《內存管理規範》文檔,Code Review重點檢查釋放完整性與歸零執行。將內存管理從「程序員自覺」上升為「團隊標準、工具輔助、流程保障」的體系化能力。