摘要

笔者最近在重新整理和编译 Nebula Graph 的第三方依赖,选出两个比较有意思的问题给大家分享一下。

Flex Segmentation Fault——Segmentation fault (core dumped)

在编译 Flex 过程中,遇到了 Segmentation fault:

make[2]: Entering directory '/home/dutor/flex-2.6.4/src' ./stage1flex   -o stage1scan.c ./scan.l make[2]: *** [Makefile:1696: stage1scan.c] Segmentation fault (core dumped)

使用 gdb 查看 coredump:

Core was generated by `./stage1flex -o stage1scan.c ./scan.l'. Program terminated with signal SIGSEGV, Segmentation fault. #0  flexinit (argc=4, argv=0x7ffd25bea718) at main.c:976 976             action_array[0] = '\0'; (gdb) disas Dump of assembler code for function flexinit:    0x0000556c1b1ae040 <+0>:     push   %r15    0x0000556c1b1ae042 <+2>:     lea    0x140fd(%rip),%rax        # 0x556c1b1c2146    ...    0x0000556c1b1ae20f <+463>:   callq  0x556c1b1af460 <allocate_array> #这里申请了buffer    ... => 0x0000556c1b1ae24f <+527>:   movb   $0x0,(%rax) # 这里向buffer[0]写入一个字节,地址非法,挂掉了    ... (gdb) disas allocate_array Dump of assembler code for function allocate_array:    0x0000556c1b1af460 <+0>:     sub    $0x8,%rsp    0x0000556c1b1af464 <+4>:     mov    %rsi,%rdx    0x0000556c1b1af467 <+7>:     xor    %eax,%eax    0x0000556c1b1af469 <+9>:     movslq %edi,%rsi    0x0000556c1b1af46c <+12>:    xor    %edi,%edi    0x0000556c1b1af46e <+14>:    callq  0x556c1b19a100 <reallocarray@plt> # 调用库函数申请内存    0x0000556c1b1af473 <+19>:    test   %eax,%eax # 判断是否为 NULL    0x0000556c1b1af475 <+21>:    je     0x556c1b1af47e <allocate_array+30># 跳转至NULL错误处理    0x0000556c1b1af477 <+23>:    cltq   # 将 eax 符号扩展至 rax,造成截断    0x0000556c1b1af479 <+25>:    add    $0x8,%rsp    0x0000556c1b1af47d <+29>:    retq    ... End of assembler dump.

可以看到,问题出在了 allocate_array 函数。因为 reallocarray 返回指针,返回值应该使用 64 bit 寄存器rax,但 allocate_array 调用 reallocarray 之后,检查的却是 32 bit 的 eax,同时使用 cltq 指令将 eax 符号扩展 到 rax。原因只有一个:allocate_array 看到的 reallocarray 的原型,与 reallocarry 的实际定义不符。翻看编译日志,确实找到了 implicit declaration of function 'reallocarray' 相关的警告。configure 阶段添加