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 来调用动态库很大的可能性会是内存访问越界 阅读全文 >>

Python 调用 C 动态库(Linux)

Go 调用 C 写的动态库完整例子(Linux版) 弄完了 Go 语言如何调用动态库,又开始琢磨起 Python 怎么调用动态库,首先仍然是以前一篇中的 C 实现为例,C 函数为原型为 char * Add(char* src, int n), 由于用符号直接定位函数,所以无需 C 的头文件。本文仍然是以 Linux 平台为例,GCC 编译为动态库 so 文件。并实验了两个例子,一个为基本的类型,char* 和  int, 再一个就是在 C 中使用到了结构体指针和无类型指针(void*) 时,如何在 Python 进行调用。

测试环境为:

  1. Linux Ubuntu 20.04
  2. gcc: gcc (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
  3. Python: 3.8.10

阅读全文 >>

Go 运行期加载 C 动态库(Linux版)

前面写的一篇 Go 调用 C 写的动态库完整例子(Linux版),是在告诉编译器用 /* #cgo ...*/ 的方式去加载动态库 libadd.so,这让代码丧失了一定的灵活性,比如同样的函数由多个动态库提供了不同的实现。这就需要做到在 Go 程序中可根据不同的输入条件选择不同的动态库实现,大概是

if 条件1 {
    loadLibrary("libadd1.so")
    调用其中的实现函数 add
else if 条件 2 {
    loadLibrary("libadd2.so")
    调用其中的实现函数 add
else {
    loadLibrary("libaddx.so")
    调用其中的实现函数  add

当然上面那样写是不行的,首先每一个动态库应该在程序运行期间只加载一次,定位的函数应该要缓存起来复用。 阅读全文 >>