C/C++ 程序結束時通過 main 返回值或 exit() 參數向作業系統回報執行狀態;運行時錯誤則通過全局變量 errno 暴露。本文系統梳理 Shell 獲取返回碼、exit() 與 return 等價性、errno/strerror 錯誤處理模式。
main 返回值 / exit 碼Linux Shell 中,上一條命令的退出碼存儲在特殊變量 $? 中:
$ ./myprogram $ echo $? 0
0 表示成功,非零 表示失敗(具體碼由程序約定)。main 返回 int,return 0; 或 return -1; 直接映射到退出碼(取低 8 位)。exit(int status) 立即終止進程,status 同樣映射到 $?。exit(0) 等價於 return 0;exit(1) 常用於錯誤退出。return 只能在 main 中直接退出進程;exit 可在任意函數/深層調用中直接終止,且會執行 atexit 註冊的清理函數、刷新標準 I/O 緩衝區。errno、strerror、perror 錯誤處理三劍客系統調用/庫函數失敗時,設置全局 int errno(需 #include <errno.h>)。
errno —— 錯誤碼EACCES(13 權限拒絕)、ENOENT(2 文件不存在)、EINVAL(22 參數無效)、ENOMEM(12 內存不足)、ERANGE(34 結果溢出)。strerror(int errnum) —— 錯誤描述字符串char *msg = strerror(errno); // 返回靜態緩衝區指針,線程不安全
// 線程安全版:strerror_r(errno, buf, buflen)
printf("Error: %s\n", msg);
perror(const char *prefix) —— 打印到 stderr
FILE *fp = fopen("none.txt", "r");
if (!fp) perror("fopen"); // 輸出: fopen: No such file or directory
等價於 fprintf(stderr, "%s: %s\n", prefix, strerror(errno))。
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
int main() {
FILE *fp = fopen("data.bin", "rb");
if (!fp) {
fprintf(stderr, "Open failed: %s (errno=%d)\n", strerror(errno), errno);
exit(EXIT_FAILURE); // 標準退出碼 1
}
// ... 業務邏輯 ...
fclose(fp);
return EXIT_SUCCESS; // 0
}
項目中建議定義枚舉:
typedef enum {
APP_OK = 0,
ERR_ARGS = 1,
ERR_CONFIG = 2,
ERR_IO = 3,
ERR_NET = 4,
ERR_INTERNAL = 255
} AppExitCode;
Shell 腳本可據此分支處理:
./app
case $? in
0) echo "OK" ;;
1) echo "參數錯誤" ;;
2) echo "配置錯誤" ;;
*) echo "未知錯誤" ;;
esac
main 返回值 / exit() 參數 → Shell $? (0成功,非零失敗)。exit() 可在任意處終止,執行清理;return 僅限 main。errno → strerror/perror 獲取可讀信息。errno;errno 成功不清零。