Python 调用动态库时 Segmentation fault (core dumped) 问题

这几天一直纠缠在如何调用动态库的问题上,先是 Go 语言,而后迁移到 Python 语言。在测试 Python 调用动态库时,出现过 "Segmentation fault (core dumped)" 的问题,本文记录下怎么去寻找线索,找到并解决问题的。

出现 "Segmentation fault (core dumped)" 的原因是多方面的,比如在 C/C++ 语言中

  1. 内存访问越界(数组越界,strcpy, strcat, sprintf, strcmp 等字符串函数读写越界)
  2. 多线程使用了线程不安全的函数
  3. 多线程读写的数据未加锁保护
  4. 非法指针(NULL 指针,随意的指针类型转换
  5. 堆栈溢出(如大的分配在栈上的局部变量)

用 Python 来调用动态库很大的可能性会是内存访问越界

下面来回顾并重现 "Segmentation fault (core dumped)" 这个问题,以 Linux 平台为例,首先在准备一个 C 动态库 testsf.c 文件,内容如

用 gcc 编译得到动态库文件 libtestsf.so

$ gcc -fPIC -shared -o libtestsf.so testsf.c

试着写下面的 Python 调用代码 testsf.py

执行 python testsf.py

$ python testsf.py
Segmentation fault (core dumped)

没有更多的信息了,虽然提示说 core dumped,  但当前目录中没有发现 dumped 的 core 文件。原因是 ulimit 设置,默认时 ulimit -a 看到的

$ ulimit -a
core file size (blocks, -c) 0
......

core file size 为 0, 所以上面的 core dumped 是在撒谎,并没有生成 core 文件,我们可以用 ulimit -c unlimited(或设置一个具体数值) 打开 dump core 的选项

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

ulimit 是会话参数,所以重新连接终端后需要时又得重新执行 ulimit -c unlimited

这时再次执行 python testsf.py, 在当前目录中就会产生一个 core 文件

$ python testsf.py
Segmentation fault (core dumped)
$ ls -l core
-rw------- 1 vagrant vagrant 3235840 Aug 24 02:29 core

接下来要做的就是用 gdb 定位出问题的地方,没有 gdb 的用 yum 或 apt 自行安装

$ gdb python core           # gdb 执行程序(python) core文件

这时进到 gdb 的控制台,输入 bt, 就能看到哪里出问题了

问题就出在对 strcpy 的函数调用上,越界了。原因是 c_char_p(10) 并非我们想要的 buffer, 它是不可访问的

上面的 Python 一执行立即会被非正常终止

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

我们应该使用 ctypes 的  create_string_buffer(size)  函数来创建一个缓冲,所以正确的 Python 使用前面动态库的代码如下

再执行 python testsf.py

$ python testsf.py
hello

一切正常,以后碰到这种  segment fault 的错误,就可以尝试着用 gdb 来寻求问题的解决办法。

链接:

  1. gdb 查看coredump文件
  2. Segmentation fault (core dumped) -llinux系统内存错误报错信息
  3. Linux程序运行出现Segmentation fault (core dumped)的通用解决方法

类别: Python. 标签: . 阅读(47). 订阅评论. TrackBack.
guest
0 Comments
Inline Feedbacks
View all comments
0
Would love your thoughts, please comment.x
()
x