如何在CI流水线中检测程序未处理异常终止的退出状态?
判断程序是否因未处理异常终止
当你用system("myprogram")获取到wStatus后,需要通过POSIX定义的wait系列宏来解析进程终止状态,核心思路是区分正常退出和信号终止,再结合异常对应的信号来判断:
步骤解析
区分终止类型
- 用
WIFEXITED(wStatus)判断进程是否正常退出(通过exit()或return返回):如果返回非零值,说明是正常退出,可通过WEXITSTATUS(wStatus)获取退出码,这种情况不属于未处理异常终止。 - 用
WIFSIGNALED(wStatus)判断进程是否被信号终止:返回非零值表示进程因收到信号而意外终止,这是我们需要重点检查的情况。
- 用
识别异常对应的信号
在绝大多数POSIX系统中(如Linux、macOS),未处理的C++异常会触发默认的终止逻辑:调用abort()函数,该函数会向进程发送SIGABRT信号(信号编号为6)。因此,当WTERMSIG(wStatus)返回SIGABRT时,即可判定程序大概率因未处理异常终止(注:手动调用abort()也会触发该信号,若需更精准判断,需修改目标程序的终止逻辑)。可选:检查核心转储
部分系统支持WCOREDUMP(wStatus)宏,可用来判断进程终止时是否生成了核心转储文件,这能作为异常终止的辅助验证依据。
代码示例
#include <stdio.h> #include <sys/wait.h> #include <signal.h> int main() { auto wStatus = system("myprogram"); if (WIFSIGNALED(wStatus)) { int terminateSignal = WTERMSIG(wStatus); if (terminateSignal == SIGABRT) { printf("程序因未处理异常终止(触发SIGABRT信号)\n"); } else { printf("程序被信号 %d 终止\n", terminateSignal); } // 检查是否生成核心转储(部分系统支持) #ifdef WCOREDUMP if (WCOREDUMP(wStatus)) { printf("已生成核心转储文件\n"); } #endif } else if (WIFEXITED(wStatus)) { int exitCode = WEXITSTATUS(wStatus); printf("程序正常退出,退出码:%d\n", exitCode); } else { printf("程序终止状态未知\n"); } return 0; }
注意事项
SIGABRT是POSIX标准定义的信号,在主流系统中编号均为6,但个别非标准系统可能有差异,需根据目标环境调整。- 如果目标程序自定义了
std::terminate_handler,可能会改变终止行为(比如改为调用exit()返回特定码),此时需要对应调整判断逻辑。
内容的提问来源于stack exchange,提问作者Nicola Mori
相关产品推荐
相关产品推荐

