Dev 日誌 | 一次 Segmentation Fault 和 GCC Illegal Instruction 編譯問題排查
摘要
筆者最近在重新整理和編譯 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 或者微信公眾號上留言。
附錄
- Nebula Graph:一個開源的分散式圖資料庫
- GitHub:https://github.com/vesoft-inc/nebula
- 知乎:zhihu.com/org/nebulagraph/posts
- 微博:weibo.com/nebulagraph
相關推薦
Dev 日誌 | 一次 Segmentation Fault 和 GCC Illegal Instruction 編譯問題排查
摘要 筆者最近在重新整理和編譯 Nebula Graph 的第三方依賴,選出兩個比較有意思的問題給大家分享一下。 Flex Segmentation Fault——Segmentation fault (core dumped) 在編譯 Flex 過程中,遇到了 Segmentation fault: m
動態規劃和分治法,貪心算法以及遞歸的再一次深刻理解和體會
規劃 動態 分治法 每次體會算法都有新的感覺,刷題越多,對算法的理解感覺也就越深刻。下面我們來重新體會下分治法,動態規劃,貪心法,遞歸的理解。1.分治法: 將問題分成單獨的階段,每個階段互相不幹擾很獨立,如10米長的木棍,切成10段,每段去解決每一段的問題。(階段沒有關系)2.貪心法 站
用不到1000美元攢一臺深度學習用的電腦一次深度學習和便宜硬體的探奇
從上世紀80年代後我就再沒攢過電腦。我也相當擔心花好幾百塊,最終搞一堆我自己裝不出來的零件(或是攢出來了,但可能沒法正常工作)。不過我要告訴你,攢機是可以的!另外,整個過程也很好玩。最後你能擁有一臺通用的電腦,並能做預測,同時比筆記本快20多倍。下面是購買清單和一些細節建議:主機板主機板有不同的尺寸規格。因為
劍指offer-41:陣列中只出現一次的數字和為S的連續正數序列
題目描述 小明很喜歡數學,有一天他在做數學作業時,要求計算出9~16的和,他馬上就寫出了正確答案是100。但是他並不滿足於此,他在想究竟有多少種連續的正數序列的和為100(至少包括兩個數)。沒多久,他就得到另一組連續正數和為100的序列:18,19,20,21,22。現在把問題交給你,你
讓天下沒有難用的資料庫 » 記一次not in 和 minus的優化
優化前: select count(t.id) from test t where t.status = 1 and t.id not in (select distinct a.app_id from test2 a
【MongoDb】一次關於Oracle和MongoDb的插入和查詢效能測試
本次實驗是在筆者上學期期末一次課程實習中的一部分,現在整理出來以供參考。 本次資料用的是不同數量級別上的資料分別在Oracle和MongoDb中進行實驗的。 其中兩者的表結構一樣,都是如下欄位:
Centos檢視系統最近一次啟動時間和執行時間
1.uptime命令 [[email protected] Log_Data]$ uptime 09:18:01 up 20:17, 1 user, load average: 0.13, 0.12, 0.14 2.檢視/proc/uptime檔案計算系統啟
Linux中xargs命令的重要作用------順便分享一次面試經歷和一次實戰經歷
在某公司的某次面試中, 被問到這樣一個題目:如何刪除當前目錄和子目錄下所有的.txt檔案? 如果對linux命令不熟悉, 則看到題目就會有點傻眼。 當然, 如果你清楚xargs命令的作用, 那就好說了。 一句話:xagrs會接收管道傳過來的引數, 並傳給管
記一次跨域和nginx配置問題
請求 The per mozilla 訪問限制 clas ocs -type head 問題描述 請求是跨域請求,從a.mycompony.com到b.mycompony.com;後端設置了如下參數,表示前端允許post和get方式跨域請求 response.setHe
一次“背鍋”和“解鍋”後的反思
中秋過的真快,還沒體會到就到最後一天了。今天在圖書館,突然想寫篇與技術無關的,但是我們工作中經常發生的事情。本來不想寫這種型別的文章,怕這種文章降低自己形象顯得太low。但是一來想鍛鍊下自己的文筆敘事能力,越怕這怕那越不敢動筆,越不動筆越沒長進,總要開個頭來個正向刺激迴圈;二來相比技術型別的文章,故事型別
記一次線上 OOM 和效能優化
大家好,我是鴨血粉絲(大家會親切的喊我 「阿粉」),是一位喜歡吃鴨血粉絲的程式設計師,回想起之前線上出現 OOM 的場景,畢竟當時是第一次遇到這麼 緊髒 的大事,要好好記錄下來。 1 事情回顧 在某次週五,通過 Grafana 監控,發現線上環境突然出現CPU和記憶體飆升的情況: 但是看到網路輸出和輸入流
關於線上一次DDOS攻擊和阿里雲DDOS防護相關內容
## 問題 最近我們的一臺阿里雲伺服器 (ECS,有公網IP,Nginx 伺服器,開放了80,443),遭受到了DDOS攻擊,主要攻擊的行為是 攻擊我們443 埠。發起大量的請求。 ![image-20200604140131494](https://djxblog.oss-cn-shenzhen.ali
記一次mysql中文字符亂碼的問題排查
mysql mysql中文亂碼 mysql字符集 今天開發反應兩樣的程序往一個庫裏面插入數據正常,往另外一個庫裏面插入數據有亂碼。第一反應就是兩個數據庫關於字符集的配置不一樣。在兩個庫分別查看參數:show variables like "%char%";+--------------------
一次線上伺服器inode打滿的事故排查
早晨來到公司收到線上伺服器磁碟/目錄滿了的報警,於是登到伺服器上,使用df -h檢視磁碟情況: # df -h Filesystem Size Used Avail Use% Mounted on /dev/vda2 36G 36G 0
記一次 MongoDB 佔用 CPU 過高問題的排查
1. 引言 今天檢視監控無意間突然發現自己的伺服器上,CPU 佔用率飆升到 100%,load 升到 10 以上,登入的響應已經達到半分鐘。 馬上執行 top,發現主要是 mongodb 佔用了大量
(轉載)一次生產系統 Full GC 問題分析與排查總結
一次生產系統 Full GC 問題分析與排查總結 轉載請註明 AIQ - 最專業的機器學習大資料社群 http://www.6aiq.com AIQ 機器學習大資料 知乎專欄 點選關注 一次生產系統 Full GC 問題分
記一次yarn導致cpu飆高的異常排查經歷
yarn就先不介紹了,這次排坑經歷還是有收穫的,從日誌到堆疊資訊再到原始碼,很有意思,下面聽我說 問題描述: 叢集一臺NodeManager的cpu負載飆高。 程序還在但是看日誌已經不再向ResourceManager傳送心跳,不斷重複下文2的動作。 心跳停止一段時間後會重連上RM但是cpu仍然很高,再過
讓天下沒有難用的資料庫 » 一次資料庫上雲遷移效能下降的排查
背景介紹: 某客戶目前正在將本地的業務系統遷移上雲,測試過程中發現後臺運營系統,在rds上執行時間明顯要比線下PC上自建資料庫執行時間要慢1倍,導致客戶系統割接延期的風險。使用者線下一臺PC伺服器的效能居然還比頂配的RDS跑的快,這讓使用者對RDS的效能產生了質疑,需要立刻調查原因。 問題分析: 通
JVM效能分析 | 一次生產系統Full GC問題分析與排查總結
一次生產系統Full GC問題分析與排查總結 背景 最近某線上業務系統生產環境頻頻CPU使用率過低,頻繁告警,通過重啟可以緩解,但是過了一段時間又會繼續預警,線上兩個服務節點相繼出現CPU資源緊張,導致伺服器卡死不可用,通過告警資訊可以看到以下問題:
JVM成長之路,記錄一次記憶體溢位導致頻繁FGC的問題排查及解決
S0 S1 E O M CCS YGC YGCT FGC FGCT GCT LGCC GCC 0.00 18.29 97.31 50.26 97.42 95.25