延續上篇,本文聚焦內存分配、釋放、錯誤處理等工程核心環節。原文示例違反 C 標準、引入未定義行為、忽略資源洩露,是典型的「能跑但不能用」的代碼。
void main(void) { // 錯誤:非標準簽名
char *ptr = malloc(10);
if (NULL == ptr) { printf("Malloc failed"); return; }
// 處理...
free(ptr);
return; // 無返回值
}
// C99/C11 標準簽名
int main(void) {
char *ptr = malloc(10);
if (!ptr) {
fprintf(stderr, "Malloc failed\n");
return EXIT_FAILURE; //
}
// 業務邏輯...
free(ptr);
return EXIT_SUCCESS;
}
| 原文寫法 | 問題 | 標準做法 |
|---|---|---|
void main() | 非標準,行為未定義 | int main(void) 或 int main(int argc, char *argv[]) |
return; 無值 | 返回隨機值給 OS | return 0/EXIT_SUCCESS 或 return EXIT_FAILURE |
| 錯誤輸出用 stdout | 混淆正常/錯誤流 | fprintf(stderr, ...) |
無 free 路徑 | 內存洩露 | 所有分配路徑必須配對釋放 |
| 表達式 | 序列點位置 | 安全性 |
|---|---|---|
a = b + c | 賦值完成後 | 安全 |
f(a, b) | 所有參數求值後、進入函數前 | 參數間無序 |
a && b | a 求值後 | 安全(短路) |
a || b | a 求值後 | 安全(短路) |
a ? b : c | a 求值後 | 安全 |
a , b | a 求值後 | 安全(逗號運算符) |
i = i++ | 無序列點分隔兩次修改 | UB |
a[i++] = i | 讀寫 i 無序列點 | UB |
# GCC/Clang 推薦標誌 -Wall -Wextra -Wsequence-point -Wunsequenced # 更嚴格 -fsanitize=undefined -fsanitize-undefined-trap-on-error
EXIT_SUCCESS/FAILUREsnprintf 或手動保證結尾-Werror)C 語言給予程序員極大自由,也要求極高自律。標準合規不是教條,而是可移植、可維護、安全軟件的基石。