C waitpid-wifexite返回0,但子项正常退出

C waitpid-wifexite返回0,但子项正常退出,c,fork,waitpid,execv,C,Fork,Waitpid,Execv,我一直在编写一个生成子进程的程序,并调用waitpid来等待子进程的终止。代码如下: // fork & exec the child pid_t pid = fork(); if (pid == -1) // here is error handling code that is **not** triggered if (!pid) { // binary_invocation is an array of the child proce

我一直在编写一个生成子进程的程序,并调用
waitpid
来等待子进程的终止。代码如下:

  // fork & exec the child
  pid_t pid = fork();
  if (pid == -1)
    // here is error handling code that is **not** triggered

  if (!pid)
    {
      // binary_invocation is an array of the child process program and its arguments
      execv(args.binary_invocation[0], (char * const*)args.binary_invocation);
      // here is some error handling code that is **not** triggered
    }
  else
    {
      int status = 0;
      pid_t res = waitpid(pid, &status, 0);

      // here I see pid_t being a positive integer > 0
      // and status being 11, which means WIFEXITED(status) is 0.
      // this triggers a warning in my programs output.
    }
waitpid
的主页说明了
WIFEXITED

WIFEXITED(status)
    returns  true  if  the child terminated normally, that is, by calling exit(3) or
    _exit(2), or by returning from main().
我理解为它应该返回一个整数成功时为0,这在我的程序执行过程中不会发生,因为我观察到
WIFEXITED(status)==0

但是,从命令行执行相同的程序会导致
$?==0,并且从gdb开始会导致:

[Inferior 1 (process 31934) exited normally]
程序运行正常,除了触发的警告,这让我觉得这里发生了什么,我错过了

编辑:
正如下面的注释中所建议的,我检查了子项是否通过segfault终止,实际上,
WIFSIGNALED(status)
返回1,
WTERMSIG(status)
返回11,即
SIGSEGV


然而,我不明白的是,为什么通过execv的调用会以segfault失败,而通过gdb或shell的调用会成功

EDIT2:

我的应用程序的行为在很大程度上取决于子进程的行为,特别是在子进程在声明为
\uuuu attribute\uuuu((析构函数))
的函数中写入的文件上。
waitpid
调用返回后,此文件存在并正确生成,这意味着segfault发生在另一个析构函数中的某个地方,或我无法控制的某个地方。

在Unix和Linux系统上,从
wait
waitpid
返回的状态(或任何其他
wait
变体)具有以下结构:

bits   meaning

0-6    signal number that caused child to exit,
       or 0177 if child stopped / continued
       or zero if child exited without a signal

 7     1 if core dumped, else 0

8-15   low 8 bits of value passed to _exit/exit or returned by main,
       or signal that caused child to stop/continue
(请注意,Posix没有定义位,只定义宏,但至少Linux、Mac OS X/iOS和Solaris使用了这些位定义。还请注意,
waitpid
仅在向停止事件传递
WUNTRACED
标志时返回,在向继续事件传递
WCONTINUED
标志时返回。)

因此,状态为11意味着子级由于信号11退出,信号11为
SIGSEGV
(同样,不是Posix,而是常规)

您的程序正在将无效参数传递给
execv
(它是围绕
execve
或其他特定于内核的调用的C库包装器),或者当您
execv
它和从shell或gdb运行它时,它的运行方式不同


如果您所在的系统支持
strace
,请运行(父级)在
strace-f
下编程,查看
execv
是否引起信号。

Status 11表示孩子接收到信号11,
SIGSEGV
。如果你在平台上(如Linux),非信号出口是传递给
\u exit
exit
main
返回的低8位值的256倍具有
战略的,使用它(使用
-f
标志)查看子进程是由于对
execv
的错误调用,还是在成功执行后获得信号。@robmayoff你说得对!我不知道status变量的下位字节包含派生进程的退出状态以及信号id。感谢你指出这一点!“但我不明白的是,为什么通过execv的呼叫会因segfault而失败"“
args.binary_调用”
看起来怎么样?它从哪里来,您创建它?@Dabo是的,args.binary_调用是一个以NULL结尾的字符指针数组,这些字符指针是子应用程序及其参数的名称。我已经验证了数组是否正确。@robmayoff由于您的评论,我找到了segfault的原因。”-问题是我的应用程序改变了子进程的环境,我在独立测试中没有复制该环境,这就是为什么SEGFULT隐藏在exec环境之外。我想为此向您表示感谢,因为您将我发送到了正确的方向。因此,如果您想将您的评论作为答案,我很乐意接受:)