相关文章推荐
正直的凉茶  ·  ThreadPool 类 ...·  1 周前    · 
英勇无比的爆米花  ·  muduo笔记 ...·  1 周前    · 
会搭讪的熊猫  ·  System.Data.OracleClie ...·  2 月前    · 

手动查找C++ Segmentation fault 的位置

以下举例说明。

#1 编辑 bomb.h 和 bomb.cc ,函数SaveMapFile()用来保存当前进程的map文件,函数Explode(nullptr)可以让进程崩溃

/* bomb.h */
#ifndef BOMB_H_
#define BOMB_H_
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
class Bomb{
public:
    void Explode(const int* pstr);
    void SaveMapFile();
#endif


/* bomb.cc */
#include "bomb.h"
void Bomb::Explode(const int* ptr){
    printf("this bomb will explode: %d", *ptr);
void Bomb::SaveMapFile(){
   char cwd[128] = {0};
   getcwd(cwd, 128);
   int pid = getpid();
   char fullpath[256] = {0};
   sprintf(fullpath, "%s/%d.maps", cwd, pid);
   char cmd_buffer[512] = {0};
   //save current process maps
   sprintf(cmd_buffer, "cat /proc/%d/maps > %s\n", pid, fullpath);
   fprintf(stderr, "%s", cmd_buffer);
   system(cmd_buffer);
   fflush(stdout);


#2 编辑 CMakeLists.txt,编译出libmy_bomb.so

SET(LIBRARY_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/lib)
ADD_LIBRARY(my_bomb SHARED src/bomb.cc)


#3 编辑 test_main.cc 文件,依次调用 SaveMapFile() 和 Explode(nullptr)

/* test_main.cc */
int main(int argc, char* argv[]){
	Bomb my_bomb;
	my_bomb.SaveMapFile();
	my_bomb.Explode(nullptr);

#4 编辑 CMakeLists.txt,链接 libmy_bomb.so:

ADD_EXECUTABLE(test_main src/test_main.cc)
TARGET_LINK_LIBRARIES(test_main  ${LIBRARY_OUTPUT_PATH}/libmy_bomb.so)


#5 查看允许的core file size,如果太小则设置为unlimited

ulimit -a  #core file size (blocks, -c) 0
ulimit -c unlimited


#6 运行可执行文件,发生segmentation fault (core dumped)

./test_main
cat /proc/24589/maps > /home/hugoliu/hugo/github/test_main/build/bin/24589.maps
[1]    24589 segmentation fault (core dumped)  ./test_main


#7 查看core文件,然后输入bt查看崩溃堆栈

gdb --core core


#8 找到崩溃地址0x7f8f5768a884

Program terminated with signal SIGSEGV, Segmentation fault.
#0  0x00007f8f5768a884 in ?? ()


#9 在当前目录查找map文件,找到崩溃地址对应的库文件地址0x7f8f5768a000

7f8f5768a000-7f8f5768b000 r-xp 00000000 103:05 1241345                   /home/hugoliu/hugo/github/test_main/lib/libmy_bomb.so
7f8f5768b000-7f8f5788a000 ---p 00001000 103:05 1241345                   /home/hugoliu/hugo/github/test_main/lib/libmy_bomb.so
7f8f5788a000-7f8f5788b000 r--p 00000000 103:05 1241345                   /home/hugoliu/hugo/github/test_main/lib/libmy_bomb.so
7f8f5788b000-7f8f5788c000 rw-p 00001000 103:05 1241345                   /home/hugoliu/hugo/github/test_main/lib/libmy_bomb.so


#10 计算崩溃位置的偏移地址

0x7f8f5768a884 - 0x7f8f5768a000 = 0x884 


#11 查看动态库的符号表,并按地址排序,找到 0x884 对应的符号是 _ZN4Bomb7ExplodeEPKi

nm -n libmy_bomb.so
                 w __cxa_finalize@@GLIBC_2.2.5
                 U getcwd@@GLIBC_2.2.5
                 U getpid@@GLIBC_2.2.5
                 w __gmon_start__
                 w _ITM_deregisterTMCloneTable
                 w _ITM_registerTMCloneTable
                 w _Jv_RegisterClasses
                 U printf@@GLIBC_2.2.5
                 U sprintf@@GLIBC_2.2.5
                 U __stack_chk_fail@@GLIBC_2.4
                 U system@@GLIBC_2.2.5
00000000000006d0 T _init
0000000000000770 t deregister_tm_clones
00000000000007b0 t register_tm_clones
0000000000000800 t __do_global_dtors_aux
0000000000000840 t frame_dummy
0000000000000870 T _ZN4Bomb7ExplodeEPKi
000000000000089c T _ZN4Bomb11SaveMapFileEv
00000000000009b4 T _fini
0000000000000a00 r __GNU_EH_FRAME_HDR
0000000000000aa8 r __FRAME_END__
0000000000200df0 t __frame_dummy_init_array_entry
0000000000200df8 t __do_global_dtors_aux_fini_array_entry
0000000000200e00 d __JCR_END__
0000000000200e00 d __JCR_LIST__
0000000000200e08 d _DYNAMIC
0000000000201000 d _GLOBAL_OFFSET_TABLE_
0000000000201048 d __dso_handle
0000000000201050 B __bss_start