使用Python C API时的奇怪记忆行为
Strange memory behaviour when using Python C API
我正在尝试使用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
初始化有什么作用?
i可以在Ubuntu 16.04和Python 2.7上确认分割故障, i如果 i省略了初始化。
在另一个应用程序中查看嵌入python,有此示例
#include <Python.h>
int
main(int argc, char *argv[])
{
Py_SetProgramName(argv[0]); /* optional but recommended */
Py_Initialize();
PyRun_SimpleString("from time import time,ctimen"
"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(长ival(
有关当前的实现将在-5和256之间保留所有整数的整数对象。
也许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
,导致崩溃。
相关文章:
- 如何运行位于boost/libs/python/example/tutorial目录中的hello.cpp和Jamfil
- Pybind11:将元组列表从Python传递到C++
- 如何在c++中使用引用实现类似python的行为
- 是否可以通过C++扩展强制多个python进程共享同一内存
- 递归列出所有目录中的C++与Python与Ruby的性能
- IPC使用多个管道和分支进程来运行Python程序
- 从python中调用C++函数并获取返回值
- Python 3.7 和 excess_args 的 SWIG 问题
- Python中的for循环与C++有何不同
- 松弛原子与无同步情况下的记忆连贯性
- 使用Pybind11向Python公开Eigen::张量
- Python str to C++ to Python str
- 如何使用Python从C++中读取谷物序列化数据
- 如何在C++中使用pybind11加载一个pickle python列表
- 如何在c++中使用system()来运行包含空格的python脚本
- python集合的C++等价物是什么.计数器
- 如果C++对象的类在另一个boost模块中声明,如何使用boost将指向该对象的指针返回到python
- 从python调用openMP共享库时,未定义opnMP函数
- 使用JsonCpp将数据返回到带有pybind11的python会在python调用中产生Symbol not foun
- 使用Python C API时的奇怪记忆行为