[英]Python receives SIGSEGV while loading C++ written extension module
正確的代碼示例:
#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(2)個故意錯誤:
變量someConstant聲明但從未定義;
函數some_function定義,但從未調用過;
如果由dlopen / dlsym編譯和打開:
sf.so: undefined symbol: someConstant
按要求。 但如果由Python解釋器加載:
>>> from sf import *
Segmentation fault (core dumped)
而最奇怪的是從core-file轉儲的python的backtrace:
#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上顯示。
題:
讓我們再看看那個堆棧跟蹤
#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
的函數libstdc++.so
它調用模塊中的函數。
你的功能永遠不會被調用。 但是,你的代碼使用了std::string
並為std::string
實例化了一些函數,這些函數被包含在你的*.so
,覆蓋了完全不同的*.so
所使用的函數,並且由於某種原因而崩潰我並不完全確定為什么。
我的直覺告訴我你使用gcc
來創建*.so
而不是g++
。 您不會在鏈接時收到錯誤,因為鏈接共享對象不起作用。 加載時不會出現錯誤,因為libstdc++
恰好已經加載了。
你使用gcc
或g++
進行鏈接嗎? 嘗試使用g++
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.