C 语言中捕获段错误并打印出最后行数

因客户需要, 需要在我们的L1 程序发生段错误segmentation fault后, 要用消息的方式让高层知道。以前每次都要提供core dump 文件, 有些同学又不会看。

于是想到用信号函数来处理segmentation fault 信号, 并在这个时候发消息给L2。 另外为了方便定位, 我们需要自己知道是挂在哪一行了。

经过研究, 以下是可以直接用的代码:

1. C 代码中注册段错误的回调函数。

#include <iostream>
#include <execinfo.h>

 static void printStackTrace() {
    void* callstack[10];
    int frames = backtrace(callstack, 10);
    char** strs = backtrace_symbols(callstack, frames);

    FILE* file = fopen("segmentationFaultInfo.txt","w"); 
    if (file == NULL) { 
        return -1;
    }
    std::cout << "Stack trace:" << std::endl;
    for (int i = 0; i < frames; ++i) {
        std::cout << strs[i] << std::endl;
        fprintf(file, "%s\n", strs[i]); // 存到文件后续解析
    }

    fclose(file);
    free(strs);
    system("./parseSegmentationFault.sh"); // 解析行数
}

static void sig_handler(int signum) 
{
    // phy thread is running in background, this will be triggered by "kill -2 {pid}"
    if (SIGINT == signum )
        exit_task_g = 1;
    else if (SIGSEGV == signum) {
        printf("\nSegmentation Fault caught!\n");

        printStackTrace(); // 打印堆栈信息
    
        exit(1);
    }
}

int main(int argc, char **argv)
{
    signal(SIGSEGV, sig_handler); // 注册段错误信号

        uint8* p = NULL;

       *p = 1; // 构造的段错误代码。

}

2. 写一个脚本解析是挂在哪一行了。

parseSegmentationFault.sh

appname=phycApp  // 可执行文件名

logFile=./segmentationFaultInfo.txt

parseLog()
{
    echo "Start to pase segmeationFaultInfo:"
    cat $logFile
    addrLines=`cat $logFile|grep $appname`
    
    while IFS= read -r line; do
        tmpAddr=`echo $line|sed "s/.*\[\(0x.*\)\].*/\1/g"`
        echo "[addr $tmpAddr]:"
        addr2line -Cif -e $appname $tmpAddr

    done <<< "$addrLines"
    
}

if [ -e $logFile ];then
    parseLog
else
    echo "Error: $logFile is not exist !!!"
fi
 

3. 运行程序后可以打印出具体的行:

Segmentation Fault caught!
Stack trace:
./dpdk_bphy_phy() [0x440058]
linux-vdso.so.1(__kernel_rt_sigreturn+0) [0xffff819d05f4]
./dpdk_bphy_phy() [0x406c68]
/lib64/libc.so.6(__libc_start_main+0xe4) [0xffff81361024]
./dpdk_bphy_phy() [0x40a1b8]
Start to pase segmeationFaultInfo:
./dpdk_bphy_phy() [0x440058]
linux-vdso.so.1(__kernel_rt_sigreturn+0) [0xffff819d05f4]
./dpdk_bphy_phy() [0x406c68]
/lib64/libc.so.6(__libc_start_main+0xe4) [0xffff81361024]
./dpdk_bphy_phy() [0x40a1b8]
[addr 0x440058]:
printStackTrace
/data/jenkins/workspace/FM_5_DD_PHy@2/f95_nr_bphy/nr_phy_arm/build/../src/_AppMain.cpp:229
sig_handler
/data/jenkins/workspace/FM_5_DD_PHY_@2/f95_nr_bphy/nr_phy_arm/build/../src/_AppMain.cpp:255
sig_handler
/data/jenkins/workspace/FM_5_DD_PHY_@2/f95_nr_bphy/nr_phy_arm/build/../src/_AppMain.cpp:247
[addr 0x406c68]:
main
/data/jenkins/workspace/FM_5_DD_PHY_@2/_nr_bphy/nr_phy_arm/build/../src/_AppMain.cpp:3378  (这就是空指针那行)
[addr 0x40a1b8]:
_start
/home/jenkins/workspace/BuildToolchainAARCH64_GCC10/toolchain/gits/glibc/csu/../sysdeps/aarch64/start.S:95

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值