You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用ctypes访问C++类属性触发段错误,Valgrind下却正常

问题分析与解决思路

核心问题1:C++库编译链接方式错误

你用gcc链接C目标文件,但gcc不会自动链接C标准库(libstdc++),这会导致运行时C对象的构造、内存管理等操作出现未定义行为——编译能通过,但实际运行时依赖的C标准库符号无法正确解析,最终触发段错误。而Valgrind运行时可能通过特殊机制补全了依赖,所以能正常执行。

修复编译命令:
改用g++执行链接操作,它会自动处理C++标准库的依赖:

g++ -c -Wall -fPIC moncc.cc -o moncc.o
g++ moncc.o -shared -o test.so

(注:编译阶段的-lstdc++是多余的,编译目标文件时无需链接库,g++在链接阶段会自动添加标准库依赖)

核心问题2:ctypes未指定函数类型信息

ctypes默认将C函数的返回值解析为int类型,但64位系统中指针是8字节,int仅为4字节,这会导致CreateTest()返回的test*指针被截断成无效的4字节地址。后续调用set_value或print时传入错误指针,直接触发段错误。Valgrind的内存检查机制可能对这种截断做了兼容,因此未暴露问题。

修复wrapper.py:
为每个导出的C函数指定正确的返回值与参数类型:

#!/usr/bin/env python
# coding: utf-8

import ctypes
lib = ctypes.CDLL("test.so")

# 指定CreateTest返回类型为void*(对应C++的test*)
lib.CreateTest.restype = ctypes.c_void_p
# 指定set_value的参数类型:第一个是对象指针,第二个是int值
lib.set_value.argtypes = [ctypes.c_void_p, ctypes.c_int]
# 指定print的参数类型:对象指针
lib.print.argtypes = [ctypes.c_void_p]

class test(object):
    def __init__(self):
        self.obj = lib.CreateTest()
        
    def set_value(self,val):
        lib.set_value(self.obj,val)
        
    def print(self):
        lib.print(self.obj)

验证修复

修改后重新编译库,运行python3 main.py,即可正常输出:

Here1
Here2
valeur : 5

内容的提问来源于stack exchange,提问作者Julien B.

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 11:35:17