面试官问程序崩溃了怎么调试?

我这里简单演示一下。

前期设置

我的环境是 Ubuntu 20.04 ,默认情况下是程序崩溃是不产生 core 文件的。

首先通过 ulimit -a 查看 core 文件的大小。

image-20220524143841432

可以看到,默认情况下 core 文件的大小为 0 ,就是不生成 core 文件。

所以这里首先要通过 ulimit -c 文件大小 命令来设置文件大小。

我这里执行 ulimit -c unlimited 设置为无限大小。

可以再使用 ulimit -a 来查看设置结果。

image-20220524144433781

可以看到 core 文件大小已经设置为无限大。

需要注意的是,这种设置方法只对当前用户生效,并且重新登录也会失效。

接下来要设置默认生成的 core 文件名字的格式。

首先问一下 “男人” 关于 core 文件的信息。

man core

我们可以看到关于文件名字的如下内容。(还好没有特别复杂的单词😏)

image-20220524145111591

大概意思就是说修改 /proc/sys/kernel/core_pattern 文件中的内容可以改变 core 文件的默认命名。

这里我简单示范一下。

echo 'core-%s-%p-%t' > /proc/sys/kernel/core_pattern

core dumped 代码测试

首先写一个会产生段错误的代码,这里用空指针赋值为例。

/*
 * filename:test.cpp
 */
#include <iostream>
using namespace std;

void coredump2(int x){
    int* p = nullptr;
    *p = x;                        // 这一行出现错误
    return;
}

void coredump1(int x){
    coredump2(x);                  //         
    return;
}

int main(){   
    int a = 2;
    coredump1(a);                   // 
    cout << ++a+a++ << endl;
    cout << a+++a++ << endl;
    cout << ++a+(++a) << endl;
    return 0;
}

使用 g++ 编译,这里加上 -g 调试模式选项,-O0 不开启编译器优化, -Wall 开启所有警告信息。

g++ -o app test.cpp -O0 -Wall -g

编译成功后,执行./app会导致程序崩溃,并产生相应的 core 文件。

image-20220524151640621

接下来可以使用 gdb 调试 core 文件来定位崩溃原因。

需要执行 gdb app core-11-259677-1653376476

image-20220524152647793

此时可以定位到程序崩溃位置为 test.cpp 文件的第 9 行。

使用 bt 命令可以查看程序崩溃时的函数调用栈的情况,方便我们进一步定位问题。

image-20220524152834389

OK !

距离拿到 offer 又进了一步。😂

那么,另一个问题来了,如果主函数中删除掉 coredump1 函数的调用,程序的输出是多少呢?😏

感兴趣的同学试验一下,期待路过的大佬留言给我解释一下,我是解释不通了。😥