gpt4 book ai didi

python - 使用 Python C API 时奇怪的内存行为

转载 作者:行者123 更新时间:2023-11-30 05:04:23 26 4
gpt4 key购买 nike

我正在尝试通过 C++ 库使用 Python C API 实现 Python 包装器。我需要实现转换,以便可以在 Python 和 C++ 中使用对象。我过去已经这样做了,但我有一个错误,我真的很难接受。

我有一个非常基本的测试功能:

PyObject* convert_to_python() {
std::cout << "Convert to PyObject" << std::endl;
long int a = 20;
PyObject* py_a = PyInt_FromLong(a);
std::cout << "Convert to PyObject ok" << std::endl;
return py_a;
}

我在 GoogleTest 宏中调用这个函数:

TEST(Wrapper, ConvertTest) {
PyObject *py_m = convert_to_python();
}

我的输出是:

Convert to PyObject
Segmentation fault (core dumped)

我还在上面运行了 valgrind:

valgrind --tool=memcheck --track-origins=yes --leak-check=full ./my_convert

但它并没有给我太多关于它的信息:

Invalid read of size 8
==19030== at 0x4F70A7B: PyInt_FromLong (in /usr/lib/x86_64-linux-gnu/libpython2.7.so.1.0)
==19030== by 0x541E6BF: _object* pysmud_from<float>(smu::Matrix<float, 0, 0>&) (smu_type_conversions.cpp:308)
==19030== by 0x43A144: (anonymous namespace)::Wrapper_ConvertMatrix_Test::Body() (test_wrapper.cpp:12)
==19030== by 0x43A0C6: (anonymous namespace)::Wrapper_ConvertMatrix_Test::TestBody() (test_wrapper.cpp:10)
==19030== by 0x465B4D: void testing::internal::HandleSehExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (gtest.cc:2078)
==19030== by 0x460684: void testing::internal::HandleExceptionsInMethodIfSupported<testing::Test, void>(testing::Test*, void (testing::Test::*)(), char const*) (gtest.cc:2114)
==19030== by 0x444C05: testing::Test::Run() (gtest.cc:2151)
==19030== by 0x4454C9: testing::TestInfo::Run() (gtest.cc:2326)
==19030== by 0x445BEA: testing::TestCase::Run() (gtest.cc:2444)
==19030== by 0x44CF41: testing::internal::UnitTestImpl::RunAllTests() (gtest.cc:4315)
==19030== by 0x46712C: bool testing::internal::HandleSehExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (gtest.cc:2078)
==19030== by 0x461532: bool testing::internal::HandleExceptionsInMethodIfSupported<testing::internal::UnitTestImpl, bool>(testing::internal::UnitTestImpl*, bool (testing::internal::UnitTestImpl::*)(), char const*) (gtest.cc:2114)
==19030== Address 0x0 is not stack'd, malloc'd or (recently) free'd

我认为这段代码应该可以工作,但我无法理解我所写的代码有什么问题。我是否错误地包含或链接了 Python 文件和库?

编辑:没有错误

#include <Python.h>

PyObject* convert_long_int(long int a) {
PyObject *ret = PyInt_FromLong(a);
return ret;
}

int main(void) {
long int a = 65454984;
PyObject *pya = convert_long_int(a);
return 0;
}

如果用gcc -o wraptest -I/usr/include/python2.7 wraptest.c -L/usr/lib/x86_64-linux-gnu/-lpython2.7 编译

初始化有什么作用?

最佳答案

我可以确认 Ubuntu 16.04 和 Python 2.7 上的段错误,如果我省略了初始化。

查看Embedding Python in Another Application , 有这个例子

#include <Python.h>

int
main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctime\n"
"print 'Today is',ctime(time())\n");
Py_Finalize();
return 0;
}

所以当我做一个等效的最小主函数时

int main()
{
Py_Initialize();
PyObject *p = convert_to_python();
Py_Finalize();
return 0;
}

它没有崩溃。


两个例子的区别在于

long int a = 20;

long int a = 65454984;

我想,这与 PyInt_FromLong(long ival) 有关

The current implementation keeps an array of integer objects for all integers between -5 and 256, when you create an int in that range you actually just get back a reference to the existing object.

也许 Python 试图在没有初始化的情况下访问未初始化的指针或内存范围。

当我使用 a = 256 更改示例时,它崩溃了。使用 a = 257,它不会。


查看cpython/Objects/intobject.c:79 ,你可以看到一个指针数组

static PyIntObject *small_ints[NSMALLNEGINTS + NSMALLPOSINTS];

可在下方 PyInt_FromLong(long ival) 中访问

v = small_ints[ival + NSMALLNEGINTS];
Py_INCREF(v);

但没有从 _PyInt_Init(void) 初始化

for (ival = -NSMALLNEGINTS; ival < NSMALLPOSINTS; ival++) {
if (!free_list && (free_list = fill_free_list()) == NULL)
return 0;
/* PyObject_New is inlined */
v = free_list;
free_list = (PyIntObject *)Py_TYPE(v);
(void)PyObject_INIT(v, &PyInt_Type);
v->ob_ival = ival;
small_ints[ival + NSMALLNEGINTS] = v;
}

这些指针都是NULL,导致崩溃。

关于python - 使用 Python C API 时奇怪的内存行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48923810/

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