为什么std::system重定向输出到文件时返回不同的退出状态
问题现象原理说明
这个差异是/bin/sh的执行优化逻辑和退出状态转换规则共同作用的结果,核心逻辑如下:
- 首先明确
std::system的执行规则:std::system内部会启动/bin/sh -c "传入的命令字符串",你拿到的返回值本质是sh进程的退出状态,而非直接是你执行的my_subprocess的退出状态。 - 无重定向时的优化逻辑:当sh执行的是无重定向、无管道、无其他shell语法的单个简单命令时,sh会做性能优化:不需要额外fork子进程,直接调用
execve把自身进程替换为my_subprocess的镜像。这种场景下,sh进程完全被my_subprocess替代,所以my_subprocess触发SIGABRT(信号6)终止的状态会直接被你的测试程序捕获,因此WIFSIGNALED(status1)为真,解析得到信号6。 - 有重定向时的执行逻辑:当命令带重定向(比如
>out.txt)时,sh无法直接做exec优化:它需要先完成重定向操作(打开out.txt文件、把标准输出的文件描述符指向打开的文件),这些操作必须在sh进程内部完成,不能替换成my_subprocess再执行。所以此时sh会先fork出子进程运行my_subprocess,自身调用waitpid等待子进程退出。
按照POSIX标准和主流shell的实现规则:如果等待到的子进程是被信号终止的,sh自身会以正常退出的状态结束,退出码为128 + 信号编号,你测试中SIGABRT的编号是6,所以计算得到退出码134,因此WIFEXITED(status2)为真,解析得到退出码134。
你可以自行验证:只要命令中包含shell层面的语法(比如管道my_subprocess | cat、变量赋值a=1 my_subprocess等),都会触发同样的退出码转换,和重定向的效果一致。
内容的提问来源于stack exchange,提问作者tjwrona
相关产品推荐
相关产品推荐

