摘要

笔者最近在重新整理和编译 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 阶段添加 CFLAGS=-D_GNU_SOURCE 即可解决此问题。

注:此问题不是必现,但编译/链接选项 -pie 和 内核参数 kernel.randomize_va_space 有助于复现。

总结:

  • 隐式声明的函数在 C 中,返回值被认为是 int
  • 关注编译器告警,-Wall -Wextra 要打开,开发模式下最好打开 -Werror。

GCC Illegal Instruction——internal compiler error: Illegal instruction

前阵子,接到用户反馈,在编译 Nebula Graph 过程中遭遇了编译器非法指令的错误,详见(#978)[https://github.com/vesoft-inc/nebula/issues/978]

错误信息大概是这样的:

Scanning dependencies of target base_obj_gch
[ 0%] Generating Base.h.gch
In file included from /opt/nebula/gcc/include/c++/8.2.0/chrono:40,
from /opt/nebula/gcc/include/c++/8.2.0/thread:38,
from /home/zkzy/nebula/nebula/src/common/base/Base.h:15:
/opt/nebula/gcc/include/c++/8.2.0/limits:1599:7: internal compiler error: Illegal instruction
min() _GLIBCXX_USE_NOEXCEPT { return FLT_MIN; }
^~~
0xb48c5f crash_signal
../.././gcc/toplev.c:325
Please submit a full bug report,
with preprocessed source if appropriate.

既然是 internal compiler error,想必是 g++ 本身使用了非法指令。为了定位具体的非法指令集及其所属模块,我们需要复现这个问题。幸运的是,下面的代码片段就能触发:

#include <thread>
int main()
{
return 0;
}

非法指令一定会触发 SIGILL,又因为 g++ 只是编译器的入口,真正干活的是 cc1plus。我们可以使用 gdb 来运行编译命令,抓住子进程使用非法指令的第一现场:

$ gdb --args /opt/nebula/gcc/bin/g++ test.cpp
gdb> set follow-fork-mode child
gdb> run
Starting program: /opt/nebula/gcc/bin/g++ test.cpp
[New process 31172]
process 31172 is executing new program: /opt/nebula/gcc/libexec/gcc/x86_64-pc-linux-gnu/8.2.0/cc1plus
Thread 2.1 "cc1plus" received signal SIGILL, Illegal instruction.
[Switching to process 31172]
0x00000000013aa0fb in __gmpn_mul_1 ()
gdb> disas
...
0x00000000013aa086 <+38>: mulx (%rsi),%r10,%r8
...

Bingo!mulx 属于 BMI2 指令集,报错机器 CPU 不支持该指令集。
仔细调查,引入该指令集的是 GCC 的依赖之一,GMP。默认情况下,GMP 会在 configure 阶段探测当前机器的 CPU 具体类型,以期最大化利用 CPU 的扩展指令集,提升性能,但却牺牲了二进制的可移植性。解决方法是,configure 之前,使用代码目录中的 configfsf.guess configfsf.sub 替换或者覆盖默认的 config.guess 和 config.sub

总结:

  • 某些依赖可能因为性能或者配置的原因,造成二进制的不兼容。
  • 缺省参数下,GCC 为了兼容性,不会使用较新的指令集。
  • 为了平衡兼容性和性能,你需要做一些额外的工作,比如像 glibc 那样在运行时选择和绑定某个具体实现。

最后,如果你想尝试编译一下 Nebula 源代码可参考以下方式:

bash> git clone https://github.com/vesoft-inc/nebula.git
bash> cd nebula && ./build_dep.sh N

有问题请在 GitHub 或者微信公众号上留言。

附录

Dev 日志 | 一次 Segmentation Fault 和 GCC Illegal Instruction 编译问题排查 NebulaGraph的更多相关文章

  1. segmentation fault

    今天在hanoi问题上出现了segmentation fault 在gcc编译的过程中 没出现error,然而程序运行到一半就出现segmentation fault: 上网发现 这条语句是非法的内存 ...

  2. 记一次PHP“Segmentation fault”调试经历

    遇到的问题: 在linux上安装php5.5.26.phalcon2.0扩展.xhprof扩展,均正常安装,并可单独运行.但放在一起运行时出现“Segmentation fault”错误.注:xhpr ...

  3. Linux下的段错误(Segmentation fault)

    Linux开发中常见段错误问题原因分析 1 使用非法的内存地址(指针),包括使用未经初始化及已经释放的指针.不存在的地址.受系统保护的地址,只读的地址等,这一类也是最常见和最好解决的段错误问题,使用G ...

  4. Python调用C的SDK出现返回值不符合预期以及Segmentation fault

    1.sdk返回值不是int型 1.1 登录函数调用 def login(ip, port, username, password, device_info, error_code):"&qu ...

  5. Segmentation Fault错误原因总结

    最近在项目上遇到了Segmentation Fault的错误,一直调试不出来是哪里出了问题,对于刚接触嵌入式的,也不知道该如何去调试一个项目,定位内存问题,纠结了好几天,好阿红整理下自己的思路.从头开 ...

  6. onvif规范的实现:onvif开发常用调试方法 和常见的segmentation fault错误

    在前几篇中,虽然已经实现了rtsp视频流的对接,但是还要做的工作还非常多,onvif本来就是一个覆盖面非常广的一个协议,每一个功能都要填充大量的函数.而且稍不注意就会出现segmentation fa ...

  7. linux backtrace()详细使用说明,分析Segmentation fault【转】

    转自:http://velep.com/archives/1032.html 在此之前,开发eCos应用程序时,经常碰到程序挂掉后,串口打印输出一大串让人看不懂的数据.今天才明白,原来这些数据是程序挂 ...

  8. 记录一次apache错误:“child pid 29023 exit signal Segmentation fault (11)”

    目前做了一台公网的测试机,主要是  php 5.3.3 版本,是 browser  --> nginx  --> apache --> php 今天因为想要安装一个商城,要求需要 P ...

  9. TQ2440实现触摸屏和qt图形 解决segmentation fault

    使用触摸屏,首先安装触摸屏矫正程序. 下载并解压tslib-1.4,进入主文件夹,运行: 1 [root@localhost ~]#./autogen.sh 2 [root@localhost ~]# ...

随机推荐

  1. MariaDB数据库

      MySQL作者Michael Widenius自己创办了新公司Monty Program AB,在MySQL基础上新创了MariaDB开源数据库.MariaDB带来更好的数据库管理特性,更好的自由 ...

  2. ubuntu16.04 gcc升级到7.3

    下载gcc- wget https://mirrors.ustc.edu.cn/gnu/gcc/gcc-7.3.0/gcc-7.3.0.tar.gz 运行 download_prerequisites ...

  3. Knative 实战:基于 Kafka 实现消息推送

    作者 | 元毅 阿里云智能事业群高级开发工程师 导读:当前在 Knative 中已经提供了对 Kafka 事件源的支持,那么如何基于 Kafka 实现消息推送呢?本文作者将以阿里云 Kafka 产品为 ...

  4. webpack 打包 todolist 应用

    写在前面的话:  一直想着手动配置webpack实现应用,正好最近这段时间比较空闲,就写了一个通过webpack打包实现todolist的简单应用.本文内容包括:通过webpack打包css,html ...

  5. 解决git报错“The file will have its original line endings in your working directory”的方法

    在执行命令 git commit --all -m  '说明' 时报错“The file will have its original line endings in your working dir ...

  6. ESP8266开发之旅 应用篇① 局域网应用 ——炫酷RGB彩灯

    1.前言     这一篇,博主将教大家怎么去实现一个WiFi RGB彩灯.     先来一个博主已经实现功能的图片,如下:     当然,博主也拍了运行视频,请点击 传输门. 1.1 知识储备     ...

  7. CSS盒模型以及如何解决边距重叠问题

    盒模型有两种,W3C 和IE 盒子模型 W3C定义的盒模型包括margin.border.padding.content,元素的宽度width=content的宽度 IE盒模型与W3C盒模型的唯一区别 ...

  8. mysql中if函数的正确使用姿势

    --为了今天要写的内容,运行了将近7个小时的程序,在数据库中存储了1千万条数据.-- 今天要说的是mysql数据库的IF()函数的一个实例. 具体场景如下, 先看看表结构: CREATE TABLE ...

  9. 【网络安全】HTTPS为什么比较安全

    目录 HTTP和HTTPS简介 SSL协议 SSL协议的主要功能 SSL协议加密数据的原理 用户和服务器的认证流程 TLS 参考 HTTP和HTTPS简介 1. HTTP协议为什么是不安全的 http ...

  10. $POJ2942\ Knights\ of\ the\ Round\ Table$ 图论

    正解:图论 解题报告: 传送门! 一道,综合性比较强的题(我是萌新刚学$OI$我只是想练下$tarjan$,,,$QAQ$ 考虑先建个补图,然后现在就变成只有相互连边的点不能做邻居.所以如果有$K$个 ...