生産環境定位問題往往遇到各種限制,比如事後日志發現程式是收到SIGSEGV退出了(segment fault),但是因為:
- 沒配置limit
- 存儲空間不夠了
- 其他未知原因
沒有正常生成core檔案,那麼這會如何定位問題呢?
場景構造
測試程式ctest,明顯的空指針錯誤。
#include <stdio.h>
struct Ctest
{
int i;
};
int main()
{
printf("hi\n");
printf("hi\n");
struct Ctest *c;
c->i = 10;
printf("hi %d\n", c->i);
printf("hi\n");
return 0;
}
複制
執行後:
$ ./ctest
hi
hi
Segmentation fault (core dumped)
複制
但是沒有生成core檔案。
定位方法1
系統中的任何程式收到SIGSEGV都會記錄在核心日志中:
dmesg -T
[Mon Jul 11 15:51:08 2022] ctest[9040]: segfault at 0 ip 0000000000401162 sp 00007ffcc0d3a0a0 error 6 in ctest[401000+1000]
複制
這條日志的含義:
-
:程序号9040
-
:錯誤名稱segfault
-
:instruction pointer就是代碼執行位置的指針ip 0000000000401162
-
:程式執行棧指針sp 00007ffcc0d3a0a0
-
:Architecture-specific flags; see arch/*/mm/fault.c for your platform.error 6
最後的error 6是按二進制來使用的,含義需要找對應平台的fault.c中具體查詢。‘’
我們關心的隻是程式運作到哪裡報錯了,是以隻需要關注
ip 0000000000401162
$ addr2line -e ./ctest 0000000000401162
/tmp/ctest.c:14
複制
可以看到程式在執行14行的時候,收到核心的SIGSEGV。
定位方法2
dump二進制編譯資訊
objdump -d ./ctest | more
可以看到401162位置上的
movl $0xa,(%rax)
,直接看彙編代碼:
- 将立即數0xa(十進制的10)賦給寄存器rax記錄的位址
- 但是rax并沒有配置設定任何位址,是以使用非法位址越界報錯
(複雜代碼的彙編可讀性很差,建議使用方法1)
objdump -d ./ctest | more
0000000000401142 <main>:
401142: 55 push %rbp
401143: 48 89 e5 mov %rsp,%rbp
401146: 48 83 ec 10 sub $0x10,%rsp
40114a: bf 10 20 40 00 mov $0x402010,%edi
40114f: e8 dc fe ff ff callq 401030 <puts@plt>
401154: bf 10 20 40 00 mov $0x402010,%edi
401159: e8 d2 fe ff ff callq 401030 <puts@plt>
40115e: 48 8b 45 f8 mov -0x8(%rbp),%rax
401162: c7 00 0a 00 00 00 movl $0xa,(%rax) # 将立即數0xa(十進制的10)賦給寄存器rax記錄的位址
# 但是rax并沒有配置設定任何位址,是以使用非法位址越界報錯
401168: 48 8b 45 f8 mov -0x8(%rbp),%rax
40116c: 8b 00 mov (%rax),%eax
40116e: 89 c6 mov %eax,%esi
401170: bf 13 20 40 00 mov $0x402013,%edi
401175: b8 00 00 00 00 mov $0x0,%eax
40117a: e8 c1 fe ff ff callq 401040 <printf@plt>
40117f: bf 10 20 40 00 mov $0x402010,%edi
401184: e8 a7 fe ff ff callq 401030 <puts@plt>
401189: b8 00 00 00 00 mov $0x0,%eax
40118e: c9 leaveq
40118f: c3 retq
複制
使用GDB來驗證下,給位址3指派,越界通路後收到核心信号SIGSEGV
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiAjM2EzLcd3LcJzLcJzdllmVldWYtl2Pn5GcuQ2MkFGOkRGOzIDM5ITMzIjNkV2Y5YTZjZGMmZjN3YzNvw1M2gTM2AjMtUGall3LcVmdhNXLwRHdo9CXt92YucWbpRWdvx2Yx5yazF2Lc9CX6MHc0RHaiojIsJye.png)