Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

在PyCharm运行Python代码运行时出现错误导致退出:Process finished with exit code 139 (interrupted by signal 11: SIGSEGV)

139错误是Linux错误代码(参考Linux code error 139),异常导致某个进程崩溃产生的,可以出现在任何语言、程序中。其产生的原因也有很多,可能时内存泄漏、依赖的库版本不匹配、环境不满足等。在程序中只能debug逐步定位出错位置,揣测出错原因。

类似的段错误包括:SIGSEGV, SIGABRT, SIGBUS,以下转载自:程序段错误处理

SIGSEGV
SIGSEGV --- Segment Fault. The possible cases of your encountering this error are:
buffer overflow --- usually caused by a pointer reference out of range.
stack overflow --- please keep in mind that the default stack size is 8192K.
illegal file access --- file operations are forbidden on our judge system.
Example

char *p = NULL;
*p = 1;

SIGBUS
 address alignment可能会导致SIGBUS.
SIGABRT
对同一个指针free() 2次可能会产生SIGABRT
SIGBUS与SIGSEGV区别:
SIGBUS(Bus error)意味着指针所对应的地址是有效地址,但总线不能正常使用该指针。通常是未对齐的数据访问所致。
SIGSEGV(Segment fault)意味着指针所对应的地址是无效地址,没有物理内存对应该地址。
结论
SIGSEGV:  一般是非法内存访问错误;
SIGABRT:  重复释放内存则会导致;
SIGBUS :  address alignment可能会导致。

程序中处理
1. 函数说明

#include <execinfo.h>
int backtrace(void **buffer, int size);

       该函数获取当前线程的调用堆栈,获取的信息将会被存放在buffer中,它是一个指针数组,参数size用来指定buffer中可以保存多少个void元素。函数的返回值是实际返回的void元素个数。buffer中的void*元素实际是从堆栈中获取的返回地址。

char **backtrace_symbols(void *const *buffer, int size);

       该函数将backtrace函数获取的信息转化为一个字符串数组,参数buffer是backtrace获取的堆栈指针,size是backtrace返回值。函数返回值是一个指向字符串数组的指针,它包含char*元素个数为size。每个字符串包含了一个相对于buffer中对应元素的可打印信息,包括函数名、函数偏移地址和实际返回地址。
       backtrace_symbols生成的字符串占用的内存是malloc出来的,但是是一次性malloc出来的,释放是只需要一次性释放返回的二级指针即可。

void backtrace_symbols_fd(void *const *buffer, int size, int fd);

       该函数与backtrace_symbols函数功能相同,只是它不会malloc内存,而是将结果写入文件描述符为fd的文件中,每个函数对应一行。该函数可重入。

2. 首先注册信号

signal(SIGSEGV, segv_signal_handler);
signal(SIGABRT, segv_signal_handler);
signal(SIGBUS, segv_signal_handler);

3. 在信号处理函数中,打印堆栈信息
       当程序出现崩溃等异常时,会接收到内核发送给进程的异常信号,进程接收到异常信号后,可以在处理信号的时候将程序的堆栈信息打印出来,以便于程序调试。

#include <stdio.h>
#include <string.h>
#include <signal.h>
#include <stdlib.h>
#include <execinfo.h>

void segv_signal_handler(int signum)
{
#define BACKTRACE_SIZE 16
    int nptrs, i;
    void *buffer[BACKTRACE_SIZE]={0};
    char **strings;
    
    printf("\n>>>>>>>>> Catch Signal [%d] <<<<<<<<<\n", signum);
    nptrs = backtrace(buffer, BACKTRACE_SIZE);
    strings = backtrace_symbols(buffer, nptrs);
    if (!strings) {
        printf("backtrace_symbols() error");
        exit(-1);
    }
    
    printf("===== print backtrace begin =====\n");
    for (i=0; i<nptrs; i++) {
        printf("[%02d] %s\n", i, strings[i]);
    }
    printf("===== print backtrace end =====\n\n");
    
    free(strings);
    exit(-1);

4. 函数使用注意事项
backtrace() 的实现依赖于栈指针(fp寄存器),在gcc编译过程中任何非零的优化等级(-On参数)或加入了栈指针优化参数-fomit-frame-pointer后多将不能正确得到程序栈信息;
backtrace_symbols() 的实现需要符号名称的支持,在gcc编译过程中需要加入 -rdynamic 参数;
内联函数没有栈帧,它在编译过程中被展开在调用的位置;
尾调用优化(Tail-call Optimization)将复用当前函数栈,而不再生成新的函数栈,这将导致栈信息不能正确被获取。
 

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
c 环境配置 colin 主要包括三个步骤:安装编译器、配置环境变量和测试编译器。 首先,安装编译器。在安装 c 环境之前,我们需要先下载对应的编译器软件。常用的 c 编译器有 gcc、clang、MSVC 等。根据个人需求选择适合自己的编译器,并下载对应的安装包。然后,按照安装向导进行安装即可。安装完成后,我们就拥有了一个可用的 c 编译器。 接下来,配置环境变量。环境变量的配置可以使得我们在任意目录下都能够直接使用 c 编译器。首先,找到我们安装的编译器安装目录。然后,将该目录添加到系统的环境变量中。具体的配置步骤可以根据操作系统的不同而有所差异,但一般都是在控制面板或者系统设置中找到“环境变量”选项,然后添加编译器安装目录到系统的“PATH”变量中。配置完成后,我们就可以在任意目录下打开命令行终端,输入编译器命令来编译和运行 c 程序。 最后,测试编译器。经过以上两个步骤的配置,我们就可以测试我们的 c 编译器是否正常工作了。在任意目录下新建一个文本文件,将其后缀改为“.c”,比如“test.c”。然后,用任意文本编辑器打开该文件,输入一段简单的 c 代码,比如“#include <stdio.h> int main(){ printf("Hello, world!"); return 0; }”。保存文件后,回到命令行终端,进入该文件所在的目录,输入编译命令,如“gcc test.c -o test”,然后按回车键进行编译。如果没有出现错误信息,说明我们的 c 编译器已经成功配置。 综上所述,通过安装编译器、配置环境变量和测试编译器三个步骤,我们可以完成 c 环境的配置,从而能够顺利编译和运行 c 程序。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值