gpt4 book ai didi

c++ - Python 在加载 C++ 编写的扩展模块时收到 SIGSEGV

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:41:28 26 4
gpt4 key购买 nike

正确的代码示例:

#include "Python.h"
#include <string>

extern const int someConstant;

void some_function()
{
const char *begin = NULL;
const char *end = NULL;

std::string s(begin, end);
const int v = someConstant;
}

static PyMethodDef _G_methods[] =
{
{NULL, NULL, 0, NULL} /* Sentinel */
};

PyMODINIT_FUNC initsf()
{
PyObject *module;

if (!(module = Py_InitModule("sf", _G_methods)))
{
return;
}

PyObject *pyerror = PyErr_NewException("fs.error", NULL, NULL);
Py_INCREF(pyerror);


PyModule_AddObject(module, "error", pyerror);
}

这是扩展模块草案。尽可能简单。它有一个空方法表和从原始 docpage 复制的初始化函数.它包含 2(两个)故意错误:

  • 已声明但从 undefined variable someConstant;

  • 函数 some_function 已定义,但从未调用;

如果被dlopen/dlsym编译打开:

sf.so: undefined symbol: someConstant

根据需要。但是如果由 Python 解释器加载:

>>> from sf import *
Segmentation fault (core dumped)

最奇怪的是从核心文件中转储的 python 回溯:

#0  0x00000bd6 in ?? ()
#1 0xb775c057 in char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) () from /usr/local/lib/python2.7/dist-packages/sf.so
#2 0xb6f9abb6 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) () from /usr/lib/i386-linux-gnu/libstdc++.so.6
#3 0xb6c3fe30 in pkgInitConfig(Configuration&) () from /usr/lib/i386-linux-gnu/libapt-pkg.so.4.12
#4 0xb6cf959e in ?? () from /usr/lib/python2.7/dist-packages/apt_pkg.so
#5 0x081949c1 in PyEval_EvalFrameEx ()
#6 0x0819af70 in PyEval_EvalCodeEx ()
#7 0x0819bb03 in PyImport_ExecCodeModuleEx ()
#8 0x0814bd40 in ?? ()
#9 0x080a38c2 in ?? ()
#10 0x0814c6d4 in ?? ()
#11 0x081031ae in ?? ()
...

看来,Python 的加载器调用了 std::string 构造函数 :-)。

因此,堆栈已损坏。它发生在加载无效模块时或在错误处理后卸载它时。如果示例代码变化不大,就不会发生这种情况。此行为已在 Python 2.7.3/Linux Ubuntu 10/gcc 4.6.3 上观察到,绝对不会在 Python 2.7.1/FreeBSD 8.1/gcc 4.2.1 上显示。

问题:

  1. 是 Python 的 bug 还是我的示例代码有错误?

最佳答案

让我们再看看那个堆栈跟踪

#0  0x00000bd6 in ?? ()#1  0xb775c057 in char* std::string::_S_construct<char const*>(char const*, char const*, std::allocator<char> const&, std::forward_iterator_tag) () from /usr/local/lib/python2.7/dist-packages/sf.so#2  0xb6f9abb6 in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string(char const*, std::allocator<char> const&) () from /usr/lib/i386-linux-gnu/libstdc++.so.6#3  0xb6c3fe30 in pkgInitConfig(Configuration&) () from /usr/lib/i386-linux-gnu/libapt-pkg.so.4.12#4  0xb6cf959e in ?? () from /usr/lib/python2.7/dist-packages/apt_pkg.so

因此 libapt-pkg.so 中的函数调用 libstdc++.so 中的函数,后者调用模块中的函数。

您的函数永远不会被调用。但是,您的代码使用 std::string 并为 std::string 实例化一些函数,这些函数包含在您的 *.so 中,覆盖完全不同的 *.so 使用的那些,并由于某种原因崩溃,我不完全确定原因。

我的直觉告诉我,您使用 gcc 来创建您的 *.so 而不是 g++。您不会在链接时收到错误,因为链接共享对象不能那样工作。您不会在加载时收到错误,因为libstdc++巧合已经加载。

您使用的是 gcc 还是 g++ 链接?尝试使用 g++

关于c++ - Python 在加载 C++ 编写的扩展模块时收到 SIGSEGV,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13261843/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com