【问题标题】:Unix C - Portable WEXITSTATUSUnix C - 便携式 WEXITSTATUS
【发布时间】:2012-11-20 09:52:54
【问题描述】:

我正在尝试获取子进程的退出代码。在 Linux 和 FreeBSD 上,我可以这样:

[0] [ishpeck@kiyoshi /tmp]$ uname
FreeBSD
[0] [ishpeck@kiyoshi /tmp]$ cat tinker.c 
#include <stdio.h>
#include <sys/wait.h>

int main(void)
{
    FILE *proc = popen("ls", "r");
    printf("Exit code: %d\n", WEXITSTATUS(pclose(proc)));
    return 0;
}
[0] [ishpeck@kiyoshi /tmp]$ gcc tinker.c -o tinker
[0] [ishpeck@kiyoshi /tmp]$ ./tinker
Exit code: 0
[0] [ishpeck@kiyoshi /tmp]$ grep WEXITSTATUS /usr/include/sys/wait.h 
#define WEXITSTATUS(x)  (_W_INT(x) >> 8)

但是,在 OpenBSD 上,我收到了来自编译器的抱怨...

[0] [ishpeck@ishberk-00 /tmp]$ uname   
OpenBSD
[0] [ishpeck@ishberk-00 /tmp]$ cat tinker.c                                    
#include <stdio.h>
#include <sys/wait.h>

int main(void)
{
    FILE *proc = popen("ls", "r");
    printf("Exit code: %d\n", WEXITSTATUS(pclose(proc)));
    return 0;
}
[0] [ishpeck@ishberk-00 /tmp]$ gcc tinker.c -o tinker                          
tinker.c: In function 'main':
tinker.c:7: error: lvalue required as unary '&' operand
[1] [ishpeck@ishberk-00 /tmp]$ grep WEXITSTATUS /usr/include/sys/wait.h        
#define WEXITSTATUS(x)  (int)(((unsigned)_W_INT(x) >> 8) & 0xff)

我并不关心它是如何完成的,我只需要退出代码。

这让我相信我在 Mac 上也会遇到这个问题: http://web.archiveorange.com/archive/v/8XiUWJBLMIKYSCRJnZK5#F4GgyRGRAgSCEG1

有没有更便携的方式来使用 WEXITSTATUS 宏?还是有更便携的选择?

【问题讨论】:

    标签: c unix portability freebsd openbsd


    【解决方案1】:

    OpenBSD 的WEXITSTATUS 实现在其参数上使用地址运算符(一元&amp;),有效地要求其参数具有存储空间。您正在使用没有存储空间的函数的返回值调用它,因此编译器会抱怨。

    尚不清楚 OpenBSD 的 WEXITSTATUS 是否符合 POSIX,但可以通过将 pclose() 的返回值分配给变量来轻松解决该问题:

        int status = pclose(proc);
        printf("Exit code: %d\n", WEXITSTATUS(status));
    

    【讨论】:

    • 这确实消除了编译器错误,但在 OpenBSD 上的输出似乎大不相同。
    • @lshpeck 你的 OpenBSD 机器上有r 文件吗?我没有可用于测试的 OpenBSD,但如果上面的代码没有按所写的那样工作,我会感到惊讶。
    【解决方案2】:

    作为一些到达这里的人可能不会注意到的细节,BSD 目标代码需要该库:

    #include <sys/wait.h>
    

    我太编译到 LinuxBSD,而 WEXITSTATUS 在编译到Linux(使用gcc),但编译到BSD(使用clang)时失败。

    【讨论】:

      【解决方案3】:

      如果您的应用程序死亡或以其他方式被终止,则返回状态是虚假的。您需要检查状态以查看退出值是否有效。请参阅 waitpid 的手册页。

      if(WIFEXITED(status))
      {
           use WEXITSTATUS(status);
      } else if (WIFSIGNALED(status)) {
           use WTERMSIG(status);
      } else {
           oh oh
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-06-03
        • 1970-01-01
        • 1970-01-01
        • 2011-02-01
        • 2011-02-20
        • 2016-06-20
        • 2011-03-06
        • 2013-11-24
        相关资源
        最近更新 更多