Python通过Ctypes调用C函数触发SIGSEGV段错误如何排查?
段错误根因
代码存在三个直接触发内存访问错误的问题,未做ctypes类型校验是核心诱因:
- 函数名混用错误:从动态库加载的函数对象是
WKMV,后续设置返回值类型、调用函数时却用了未定义的WeightedKaplanMeierValue,会导致调用地址完全非法。 - 指针参数传值错误:C函数的
len、end、surv三个形参都是指针类型,需要传入内存地址,但代码直接传入了c_int/c_double的数值实例,C端会把传入的整数值当成内存地址去读写,直接访问受保护的内存地址触发SIGSEGV。比如传入c_int(n)值为10,C端执行*len时会尝试读内存地址0xa的内容,这是系统保留区域,必然触发段错误。 - 未显式声明参数类型:ctypes默认不会对传入参数做类型校验,没有设置
argtypes的情况下,传参错误不会在Python层抛出可定位的异常,会直接把错误数据传入C层触发内存问题。
另外还有一处逻辑错误:传入的end值为n=10,但长度为10的数组合法下标范围是0~9,会导致C函数的循环逻辑不符合预期。
修复方案
按以下步骤修改代码即可正常运行:
- 统一函数对象的使用,不要混用函数名
- 显式声明C函数的参数类型、返回值类型,让ctypes自动做参数校验
- 所有指针类型的参数,用
byref()传入对象的内存地址 - 修正
end参数的取值,按WKMV函数的逻辑,end应设为0(从数组末尾反向遍历到0下标) - 调用完成后,通过
.value属性取出c_double对象里存的Python原生浮点值
修复后的Python调用代码如下:
from ctypes import * # 加载动态库 c_funcs = CDLL('filepath/file.so') WKMV = c_funcs.WKMV # 显式声明参数和返回值类型 WKMV.argtypes = [ POINTER(c_double), # time2 POINTER(c_int), # status POINTER(c_double), # weights POINTER(c_int), # delta POINTER(c_int), # len POINTER(c_int), # end POINTER(c_double) # surv ] WKMV.restype = None def do_WKMV_using_c(): """Call C function""" n = 10 # 硬编码测试数据 time2 = [58.72, 41.9, 16.23, 145.44, 10.56, 54.95, 196.46, 194.03, 20.95, 20.0] status = [1, 1, 0, 0, 0, 0, 0, 0, 1, 0] delta = [1]*n weights = [0.5]*n surv = 1.0 end = 0 # 修正end参数为合法下标起始值 # 转换为C类型 c_arr_time2 = (c_double * n)(*time2) c_arr_status = (c_int * n)(*status) c_arr_weights = (c_double * n)(*weights) c_arr_delta = (c_int * n)(*delta) c_int_len = c_int(n) c_int_end = c_int(end) c_double_surv = c_double(surv) # 传入指针调用 WKMV( c_arr_time2, c_arr_status, c_arr_weights, c_arr_delta, byref(c_int_len), byref(c_int_end), byref(c_double_surv) ) # 取出返回值 return c_double_surv.value print(do_WKMV_using_c())
C侧详细报错获取方法
如果后续C函数还有内存问题,可以用以下方法定位:
- 带调试符号编译so:编译时加
-g -O0参数,关闭编译器优化、保留行号信息,段错误生成coredump后用gdb加载可以直接看到崩溃对应的C代码行号。 - 用AddressSanitizer检测内存错误:编译时加
-fsanitize=address -g参数,运行Python脚本时会直接输出非法内存访问的具体位置、内存操作类型,不需要手动加日志就能定位越界、野指针问题。 - 临时加stderr打印:在C函数的入口、循环节点加
fprintf(stderr, "debug info: ...\n")打印变量值,运行时可以直接看到C侧的执行流程。
内容的提问来源于stack exchange,提问作者Yury Moskaltsov
相关产品推荐
相关产品推荐

