为啥调试时生成的程序退出代码会发生变化?

Posted

技术标签:

【中文标题】为啥调试时生成的程序退出代码会发生变化?【英文标题】:Why does spawned program exit code change when debugging?为什么调试时生成的程序退出代码会发生变化? 【发布时间】:2013-07-01 04:12:37 【问题描述】:

我有一个 C++ 程序,我用它来测试另一个程序是否不会崩溃。父代码(我们称之为“parentProg”)看起来像这样:

int run(const char * command)

  ...

  int retCode = system(command);
  printf("Code is %d\n",retCode);
  if(retCode == 134) //128 + SIGABORT
  
    // Record error conditions
    ...
  

命令变量包含正在测试的程序(我们称它为“childProg”)。在以前的 Linux 发行版中,此代码按预期工作。如果 a.out 崩溃或遇到断言,它将返回 134 并且错误处理代码将运行。但是,在我升级到更新的 Linux 发行版后,情况就不再如此了。相反,当使用 GDB 或 nemiver 作为衍生程序运行时,我看到返回码为 6。奇怪的是,如果我单独运行子程序或使用 DDD,它会恢复到 134。

对于以下测试,我将 childProg 修改为以下代码:

#include <assert.h>

int main(int argc, char * argv[])

  assert(0);
  return 0;

childProg 本身

[user@localhost multi]$ ./childProg 
childProg: temp.cpp:5: int main(int, char **): Assertion `0' failed.
Abort
[user@localhost multi]$ echo $?
134

产生 childProg 的 parentProg

[user@localhost multi]$ ./parentProg 1 o
Running 1 times
childProg: temp.cpp:5: int main(int, char **): Assertion `0' failed.
Code is 6
Done 0
[user@localhost multi]$ 

使用 GDB

(gdb) run
Starting program: parentProg 1 o
Running 1 times
Detaching after fork from child process 3311.
childProg: temp.cpp:5: int main(int, char **): Assertion `0' failed.
Code is 6
Done 0
[Inferior 1 (process 3295) exited normally]
(gdb) 

使用 DDD

(gdb) run 1 o
Starting program: parentProg 1 o
Running 1 times
Detaching after fork from child process 3336.
childProg: temp.cpp:5: int main(int, char **): Assertion `0' failed.
Code is 134
Done 0
[Inferior 1 (process 3319) exited normally]
(gdb) 

这按预期工作

[me@localhost multi]$ /bin/sh -c ./childProg
childProg: temp.cpp:5: int main(int, char **): Assertion `0' failed.
Abort
[me@localhost multi]$ echo $?
134

这里可能发生了什么?除了检查退出代码之外,还有更好的方法来检查崩溃/段错误/断言吗?

【问题讨论】:

要明确一点,在调试程序时,如果它生成核心转储,则返回值与 128 进行或运算,即 WCOREDUMP。此标志在所有 UNIX 变体的所有版本上实现。 Greg 的代码 sn-p 应该为您解决问题,因为 WEXITSTATUS() 宏会忽略除包含错误代码的最低 8 位以外的所有内容,在您的情况下为 6 @Adam12 似乎在 GDB 中代码是 6,因为减去了 128。在 DDD 中没有减去 128,代码是 134。 【参考方案1】:

头文件包含用于分析返回码的宏。

要检查退出原因,您可以执行以下操作:

#include <stdio.h>
#include <sys/wait.h>

...

void run(const char *command)

    int retcode = system(command);

    if (WIFEXITED(retcode))
    
        int status = WEXITSTATUS(retcode);
        if (status)
        
            printf("Exited normally with FAILURE status of %d!\n", status);
        
        else
        
            printf("Exited normally with SUCCESS(0) status!\n");
        
    
    else if (WIFSIGNALED(retcode))
    
        int signal = WTERMSIG(retcode);
        printf("Abnormal termination - program crashed or was aborted with signal %d\n", signal);
    


有关这些宏的说明,请参阅“man waitpid”。

【讨论】:

谢谢。此代码可靠地工作。我正在根据this question 测试 134。【参考方案2】:

(134 = 6 | __WCOREFLAG)

man 2 wait

【讨论】:

以上是关于为啥调试时生成的程序退出代码会发生变化?的主要内容,如果未能解决你的问题,请参考以下文章

程序'[13476] MyApp.vshost.exe'已退出,代码为-1(0xffffffff)

为啥我在退出我的 Activity 时会崩溃?

刷新页面后,我退出了吗?为啥?

Pycharm 调试:发生错误时,程序在本地退出,但在远程可以查看变量。如何在本地激活它?

当应用程序在 Cordova 中退出时会发生啥事件?

更改代码生成后以代码 255 退出的特定代码行