在perl中,我们如何检测外部命令中的分段错误

时间:2013-08-20 10:34:22

标签: perl

以下是注定要崩溃的C代码:

#include<stdio.h>
#include<stdlib.h>

int main() {
    char *p = NULL;
    printf("Value at P: %c\n", *p);
    return 0;
}

当我编译并运行它(带有gcc 4.5.2的RH4机器)时,它可以预测会出现分段错误:

%  ./a.out
Segmentation fault

%  echo $status
139

如果我使用Perl v5.8.5运行它,就会发生这种情况:

%  perl -e 'system("./a.out") and die "Status: $?"'
Status: 11 at -e line 1.

$?的{​​{3}}文档说明了

  

因此,子流程的退出值实际为($?>> 8 )$? & 127给出了流程死亡的信号(如果有的话),$? & 128   报告是否存在核心转储。

11 >> 8011 & 12711

为什么不同的退出状态?如果我们不能依赖退出状态,那么在外部命令中检测分段错误的方法应该是什么?

2 个答案:

答案 0 :(得分:13)

阅读system的文档可能会回答您的问题:

system('a.out');

if ($? == -1) {
    print "failed to execute: $!\n";
}
elsif ($? & 127) {
    printf "child died with signal %d, %s coredump\n",
        ($? & 127),  ($? & 128) ? 'with' : 'without';
}
else {
    printf "child exited with value %d\n", $? >> 8;
}

输出:

child died with signal 11, without coredump

shell只是以不同的方式对状态中的信号进行编码:139 - 128 = 11.例如,man bash说:

  

简单命令的返回值是退出状态,如果命令被信号n终止,则返回128 + n。

答案 1 :(得分:3)

操作系统总是看到同样的事情...... wait(2)系列函数返回的内容。 system(3),et。所有,呼叫等待(2)。它是如何影响你的是造成差异的原因。 shell和程序执行不同的操作并报告不同的方式。必须向右转8才能获得最常见的退出状态,这在shell程序中会非常烦人,并且会让精通技术的用户感到困惑。

虽然我使用的第一个UNIX系统(真正的Unix)具有相同的返回值,但我总是想知道预发布版本是否不同并且返回信号和核心/转储是后来添加的。

我首选的退出状态报告往往让计算机为我分配我的位。

   my $x = $?;   #save status
   print( "Exit status: %d.%d%s\n",
              $x>>8, $x&127, ($x&128)?"*":"" );