C++ Python扩展中的间歇性段错误

-1 投票
3 回答
856 浏览
提问于 2025-04-17 09:38

我有一个Python对象,它通过HTTP访问并下载一些文本。现在我在用C++代码运行这个Python对象,并处理这些文本。

/* CPPCode.cxx */
int main(...) {
    for(int i = 0; i < numURLs; i++) {
        // Python method returns a string
        PyObject *pyValue = PyObject_CallMethod(pyObjectInstance, pyFunctionName, par1, par2....);
        string valString = PyString_AsString(pHistValue);   
        // ... process string ... 
    }
} 

/* PyObject.py */
class PyClass:
    def PyFunction(...):
        try: urlSock = urllib.urlopen(urlName)
        except ...

        while(...) :
             dataStr = urlSock.readline()
             # do some basic string processing....

        return dataStr

大多数网址都能正常工作——C++代码能获取到正确的字符串,我可以处理它,一切都很好。但是有几个特定的网址,看起来和其他网址在浏览器中基本一样,却在调用PyString_AsString()方法时导致了程序崩溃:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000000000000b2
0x000000010007716d in PyString_AsString ()

如果我打印出应该由Python方法返回的字符串(在上面的伪代码中是'dataStr'),它看起来没问题!我完全不知道是什么导致了这个问题——如果有任何建议,我将非常感激!谢谢

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

解决方案:

我使用的模板代码中有一个调用:

Py_DECREF(pyValue)

在我调用之前:

PyString_AsString(pyValue)

至于为什么在某些特定的函数调用中它会被释放,我也不知道。正如'Gecco'在下面的评论中所说,

'PyString_AsString的文档说:“指针指向字符串的内部缓冲区,而不是一个副本。数据不能以任何方式被修改,除非字符串是刚刚通过PyString_FromStringAndSize(NULL, size)创建的。它不能被释放。”'

3 个回答

0

如果你在编译C代码的时候加上-g这个调试标志(至少在GCC中是这样),那么你就可以用gnu调试器gdb来运行你的Python代码:

$ gdb /path/to/python/compiled/against 
... blah ...
(gdb) run PyObject.py

这样你就能找到你的程序崩溃的原因了。

0

我猜测 Py_DECREF 可能得到了一个空值。

1

PyString_AsString 的说明中提到:“这个指针指向的是字符串的内部存储区,而不是一个副本。除非这个字符串是刚用 PyString_FromStringAndSize(NULL, size) 创建的,否则数据不能被修改。这个存储区不能被释放。”

请确保你不要释放这个存储区

撰写回答