c - perlbench 在 SPEC 2006 线束之外导致段错误

标签 c perl debugging crash benchmarking

这可能过于具体,但张贴在这里,因为它可能会帮助那些试图在默认 SPEC 基准测试工具之外编译/运行 SPEC 2006 基准测试的其他人。 (我们这样做的原因是比较编译策略和代码覆盖率,而 SPEC 工具只关注结果代码的性能)。

执行 perlbench 的引用运行时,基准测试因段错误而崩溃:

    Program received signal SIGSEGV, Segmentation fault.
0x00000000004f6868 in S_regmatch (prog=0x832144)

    at <path-to-spec>/CPU2006/400.perlbench/src/regexec.c:3024
3024            PL_reg_start_tmp[n] = locinput;
(gdb) bt
#0  0x00000000004f6868 in S_regmatch (prog=0x832144)
    at <path-to-spec>/CPU2006/400.perlbench/src/regexec.c:3024
#1  0x00000000004f22cf in S_regtry (prog=0x8320c0, startpos=0x831e70 "o")
    at <path-to-spec>/CPU2006/400.perlbench/src/regexec.c:2196
#2  0x00000000004eba71 in Perl_regexec_flags (prog=0x8320c0, stringarg=0x831e70 "o", strend=0x831e71 "", 
    strbeg=0x831e70 "o", minend=0, sv=0x7e2528, data=0x0, flags=3)
    at <path-to-spec>/CPU2006/400.perlbench/src/regexec.c:1910
#3  0x00000000004b33bb in Perl_pp_match ()
    at <path-to-spec>/CPU2006/400.perlbench/src/pp_hot.c:1340
#4  0x00000000004fcde4 in Perl_runops_standard ()
    at <path-to-spec>/CPU2006/400.perlbench/src/run.c:37
#5  0x000000000046bf57 in S_run_body (oldscope=1)
    at <path-to-spec>/CPU2006/400.perlbench/src/perl.c:2017
#6  0x000000000046b9f6 in perl_run (my_perl=0x7bf010)
    at <path-to-spec>/CPU2006/400.perlbench/src/perl.c:1934
#7  0x000000000047add2 in main (argc=4, argv=0x7fffffffe178, env=0x7fffffffe1a0)
    at <path-to-spec>/CPU2006/400.perlbench/src/perlmain.c:98

执行环境是 64 位 Linux,并且使用最新的 gcc 和 clang 观察到行为。

导致崩溃的原因是什么?

最佳答案

段错误是由指出的行上的变量 n 的垃圾值引起的。检查代码显示该值来自以下类型对象的字段 arg1:

struct regnode_1 {
    U8  flags;
    U8  type;
    U16 next_off;
    U32 arg1;
};

检查对象的内存位置显示它没有打包,即 next_offarg1 之间有 32 位填充:

(gdb) x/16xb scan
0x7f4978:       0xde    0x2d    0x02    0x00    0x00    0x00    0x00    0x00
0x7f4980:       0x00    0x11    0x0d    0x00    0x00    0x00    0x00    0x00
(gdb) print/x n
$1 = 0xd1100

这很可疑。 perlbench 中正在进行指针和类型转换,因此类型大小假设可能在某处失败。使用 multilib 编译产生一个工作基准并检查内存以验证没有填充。

在执行 64 位编译时将结构强制放入位域修复了崩溃:

struct regnode_1 {
    U8  flags : 8;
    U8  type : 8;
    U16 next_off : 16;
    U32 arg1 : 32;
};

关于c - perlbench 在 SPEC 2006 线束之外导致段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40219744/

相关文章:

c - 结构体/构造函数/指针 - C 编程语言

perl - 对 SQLite 数据库的仅内存修改

java - 线程 "main"java.util.InputMismatchException 中出现错误异常

java - Android 语音调用桌面

c - SIGSEGV 处理程序无法退出

c - 服务器的线程与客户端实现通信

Perl Parallel::ForkManager wait_all_children() 耗时过长

perl - 如何在 Perl 中复制只读目录?

debugging - 如果图像在只读内存中,调试器如何设置断点?

c++ - Pretty Printers 用于在 Mac OS 中使用 Eclipse/CDT 调试 C++ 代码