本文主要讲述Linux下运行程序时发生Segmentation Fault的定位方法。


一 准备工作

首先需要做点准备工作,

  1. 安装gcc和gdb
  2. 打开终端,然后输入以下命令开启ulimit
    	ulimit -c unlimited # 打开ulimit
    	ulimit -c # 如果打开成功会返回unlimited
    
    PS:以上开启ulimit的操作只会在当前终端下有效

二 示例

一个简单C程序如下,

#include <stdio.h>

int main(void)
{
	int * ptr = NULL;
	*ptr = 100; // 发生Segmentation Fault的地方
	
	printf("hello world\n");
	return 0;
}
1. 编译运行

编译,需要使用-g选项

gcc main.c -g -o main

然后执行main,

./main

这样就会出现Segmentation Fault,特别注意后面括号里的"core dumped",如果没有开启ulimit就不会出现这个信息。
在这里插入图片描述
并且在当前目录下出现core文件,
在这里插入图片描述

2. 解析core文件

使用gdb解析core文件,

gdb ./main ./core

打印如下,
在这里插入图片描述
会提示在程序中的哪一行造成Segmentation Fault,非常方便。

通常来说我们遇到的都是比较大的工程,如果只是知道哪个位置发生的Segmentation Fault还是不够,还需要知道出错点的调用者,这个时候可以使用bt命令,该命令可以打印函数调用栈。

如下

#include <stdio.h>


void func()
{
	int * ptr = NULL;
	*ptr = 100; // 发生Segmentation Fault的地方

    printf("hello world\n");
}

int main(void)
{

	func();
	
	return 0;
}

bt执行后如下,可以看到函数调用栈,非常清晰
在这里插入图片描述


三 结合CMake

对于简单的程序,直接命令行敲两下就行了,但是对于中大型工程,就需要借助一些工具,如CMake

我们重新组织一下工程,如下,
在这里插入图片描述
CMakeLists.txt内容如下,

cmake_minimum_required (VERSION 3.5)

project (demo)

add_executable(main main.c)

set (EXECUTABLE_OUTPUT_PATH ${PROJECT_SOURCE_DIR}/bin)

在终端下cd到build目录下执行,通过使用CMAKE_BUILD_TYPE,可以很方便生成debug版本的程序,

cmake -DCMAKE_BUILD_TYPE=Debug ..  && make

接着就是cd到bin目录下去执行main,来产生core,最后解析core。

有问题的地方修改ok后,再次使用CMAKE_BUILD_TYPE去生成release版本的程序,

cmake -DCMAKE_BUILD_TYPE=Release ..  && make

非常方便。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐