应用程序在C++的Python扩展函数中随机出现段错误
我在用C++扩展Python时遇到了一些奇怪的问题。任何帮助或建议都非常感谢。
先说明一下情况。
我在C++中嵌入了Python,用来执行Python脚本。同时,我也在C++中使用了Python扩展,这样Python脚本就可以调用C++的函数。
问题是什么呢?
当我把模块“方法表”中的方法入口注释掉时,如下所示,应用程序从来没有崩溃过,也没有遇到段错误。
static PyMethodDef sa_methods[] = { //{"GetBlue",(PyCFunction)sa_GetBlue,METH_VARARGS,PyDoc_STR("fetches Blue color")}, //{"GetRed",(PyCFunction)sa_GetRed,METH_VARARGS,PyDoc_STR("fetches Red color")}, {"GetYellow",(PyCFunction)sa_GetYellow,METH_VARARGS,PyDoc_STR("fetches yellow color")}, {"GetPink",(PyCFunction)sa_GetPink,METH_VARARGS,PyDoc_STR("fetches pink color")}, {NULL, NULL, 0, NULL} };
但是当我把方法入口的注释去掉时,如下所示,应用程序在处理20000到50000个请求时总是会随机崩溃。
static PyMethodDef sa_methods[] = { {"GetBlue",(PyCFunction)sa_GetBlue,METH_VARARGS,PyDoc_STR("fetches Blue color")}, {"GetRed",(PyCFunction)sa_GetRed,METH_VARARGS,PyDoc_STR("fetches Red color")}, {"GetYellow",(PyCFunction)sa_GetYellow,METH_VARARGS,PyDoc_STR("fetches yellow color")}, {"GetPink",(PyCFunction)sa_GetPink,METH_VARARGS,PyDoc_STR("fetches pink color")}, {NULL, NULL, 0, NULL} };
我把上面提到的两个方法留空,它们只是简单地返回了Py_False。
下面是我每次遇到的堆栈跟踪信息。
#0 0x00002b700146c4d7 in PyNumber_CoerceEx (pv=0x41801798, pw=0x41801790) at Objects/object.c:1599
#1 0x00002b700142d6e3 in binary_op1 (v=0x2aaaac079600, w=0x2b7001750550, op_slot=16) at Objects/abstract.c:929
#2 0x00002b7001431e08 in PyNumber_Multiply (v=0x41801798, w=0x41801790) at Objects/abstract.c:1188
#3 0x00002b70014c4326 in PyEval_EvalFrameEx (f=0x8127780, throwflag=<value optimized out>) at Python/ceval.c:1118
#4 0x00002b70014c8493 in call_function (f=0x996e660, throwflag=<value optimized out>) at Python/ceval.c:3792
#5 PyEval_EvalFrameEx (f=0x996e660, throwflag=<value optimized out>) at Python/ceval.c:2389
#6 0x00002b70014c8493 in call_function (f=0x2aaac30aeb50, throwflag=<value optimized out>) at Python/ceval.c:3792
#7 PyEval_EvalFrameEx (f=0x2aaac30aeb50, throwflag=<value optimized out>) at Python/ceval.c:2389
#8 0x00002b70014c8d9f in PyEval_EvalCodeEx (co=0x2aaaad7dc558, globals=<value optimized out>, locals=<value optimized out>, args=0x2aaac6ab59a0, argcount=2,
kws=0x2aaac6ab59b0, kwcount=0, defs=0x7819128, defcount=1, closure=0x0) at Python/ceval.c:2968
#9 0x00002b70014c6df3 in call_function (f=0x2aaac6ab57d0, throwflag=<value optimized out>) at Python/ceval.c:3802
#10 PyEval_EvalFrameEx (f=0x2aaac6ab57d0, throwflag=<value optimized out>) at Python/ceval.c:2389
#11 0x00002b70014c8d9f in PyEval_EvalCodeEx (co=0x2aaabdf8e828, globals=<value optimized out>, locals=<value optimized out>, args=0x2aaac65bcbf0, argcount=2,
kws=0x2aaac65bcc00, kwcount=0, defs=0x7819c28, defcount=1, closure=0x0) at Python/ceval.c:2968
#12 0x00002b70014c6df3 in call_function (f=0x2aaac65bca40, throwflag=<value optimized out>) at Python/ceval.c:3802
#13 PyEval_EvalFrameEx (f=0x2aaac65bca40, throwflag=<value optimized out>) at Python/ceval.c:2389
#14 0x00002b70014c8493 in call_function (f=0x2aaac6301630, throwflag=<value optimized out>) at Python/ceval.c:3792
#15 PyEval_EvalFrameEx (f=0x2aaac6301630, throwflag=<value optimized out>) at Python/ceval.c:2389
#16 0x00002b70014c8d9f in PyEval_EvalCodeEx (co=0x6c7f558, globals=<value optimized out>, locals=<value optimized out>, args=0x2aaac55963e8, argcount=2,
kws=0x2aaac55963f8, kwcount=0, defs=0xd83fce8, defcount=1, closure=0x0) at Python/ceval.c:2968
#17 0x00002b70014c6df3 in call_function (f=0x2aaac5596240, throwflag=<value optimized out>) at Python/ceval.c:3802
#18 PyEval_EvalFrameEx (f=0x2aaac5596240, throwflag=<value optimized out>) at Python/ceval.c:2389
#19 0x00002b70014c8d9f in PyEval_EvalCodeEx (co=0x6c7fcd8, globals=<value optimized out>, locals=<value optimized out>, args=0x2aaac6fbc328, argcount=2,
kws=0x2aaac6fbc338, kwcount=0, defs=0xd83fc68, defcount=1, closure=0x0) at Python/ceval.c:2968
#20 0x00002b70014c6df3 in call_function (f=0x2aaac6fbc1a0, throwflag=<value optimized out>) at Python/ceval.c:3802
#21 PyEval_EvalFrameEx (f=0x2aaac6fbc1a0, throwflag=<value optimized out>) at Python/ceval.c:2389
#22 0x00002b70014c8d9f in PyEval_EvalCodeEx (co=0x6c7f648, globals=<value optimized out>, locals=<value optimized out>, args=0x1, argcount=0, kws=0x2aaac3e32558,
kwcount=0, defs=0xd83ffa8, defcount=1, closure=0x0) at Python/ceval.c:2968
#23 0x00002b70014c6df3 in call_function (f=0x2aaac3e323d0, throwflag=<value optimized out>) at Python/ceval.c:3802
#24 PyEval_EvalFrameEx (f=0x2aaac3e323d0, throwflag=<value optimized out>) at Python/ceval.c:2389
#25 0x00002b70014c8d9f in PyEval_EvalCodeEx (co=0x2aaaad7f70a8, globals=<value optimized out>, locals=<value optimized out>, args=0x0, argcount=0, kws=0x1325c6a8,
kwcount=0, defs=0x0, defcount=0, closure=0x2aaaad18e990) at Python/ceval.c:2968
#26 0x00002b70014c6df3 in call_function (f=0x1325c480, throwflag=<value optimized out>) at Python/ceval.c:3802
#27 PyEval_EvalFrameEx (f=0x1325c480, throwflag=<value optimized out>) at Python/ceval.c:2389
#28 0x00002b70014c8d9f in PyEval_EvalCodeEx (co=0x2aaaad7f77b0, globals=<value optimized out>, locals=<value optimized out>, args=0x1, argcount=1, kws=0x2aaac5ec1d08,
kwcount=0, defs=0x2aaaacfdf5e8, defcount=1, closure=0x0) at Python/ceval.c:2968
#29 0x00002b70014c6df3 in call_function (f=0x2aaac5ec1b00, throwflag=<value optimized out>) at Python/ceval.c:3802
#30 PyEval_EvalFrameEx (f=0x2aaac5ec1b00, throwflag=<value optimized out>) at Python/ceval.c:2389
#31 0x00002b70014c8493 in call_function (f=0xa926080, throwflag=<value optimized out>) at Python/ceval.c:3792
#32 PyEval_EvalFrameEx (f=0xa926080, throwflag=<value optimized out>) at Python/ceval.c:2389
#33 0x00002b70014c8493 in call_function (f=0x8e4bd40, throwflag=<value optimized out>) at Python/ceval.c:3792
#34 PyEval_EvalFrameEx (f=0x8e4bd40, throwflag=<value optimized out>) at Python/ceval.c:2389
#35 0x00002b70014c8d9f in PyEval_EvalCodeEx (co=0x2aaabc9f7648, globals=<value optimized out>, locals=<value optimized out>, args=0x9ff5f58, argcount=1,
---Type <return> to continue, or q <return> to quit---
kws=0x9ff5f60, kwcount=0, defs=0x0, defcount=0, closure=0x2aaaacfdfc50) at Python/ceval.c:2968
#36 0x00002b70014c6df3 in call_function (f=0x9ff5dc0, throwflag=<value optimized out>) at Python/ceval.c:3802
#37 PyEval_EvalFrameEx (f=0x9ff5dc0, throwflag=<value optimized out>) at Python/ceval.c:2389
#38 0x00002b70014c8493 in call_function (f=0xdb993e0, throwflag=<value optimized out>) at Python/ceval.c:3792
#39 PyEval_EvalFrameEx (f=0xdb993e0, throwflag=<value optimized out>) at Python/ceval.c:2389
#40 0x00002b70014c8d9f in PyEval_EvalCodeEx (co=0x2aaabd820990, globals=<value optimized out>, locals=<value optimized out>, args=0x2aaaacfdf8a8, argcount=1, kws=0x0,
kwcount=0, defs=0x0, defcount=0, closure=0x0) at Python/ceval.c:2968
#41 0x00002b700145815d in function_call (func=0x7d898c0, arg=0x2aaaacfdf890, kw=0x0) at Objects/funcobject.c:524
#42 0x00002b700142d318 in PyObject_Call (func=0x7d898c0, arg=0x2aaaacfdf890, kw=0x0) at Objects/abstract.c:2492
#43 0x00002b700143cd7f in instancemethod_call (func=<value optimized out>, arg=0x2aaaacfdf890, kw=0x0) at Objects/classobject.c:2579
#44 0x00002b700142d318 in PyObject_Call (func=0x7554690, arg=0x2aaaac04d050, kw=0x0) at Objects/abstract.c:2492
#45 0x00002b70014c0e16 in PyEval_CallObjectWithKeywords (func=0x7554690, arg=0x2aaaac04d050, kw=0x0) at Python/ceval.c:3575
#46 0x00002b70014f9dcd in t_bootstrap (boot_raw=0x2aaac76e67c0) at ./Modules/threadmodule.c:425
#47 0x00000033c720677d in start_thread () from /lib64/libpthread.so.0
#48 0x00000033c66d33ed in clone () from /lib64/libc.so.6
1 个回答
5
我找到了这个问题的解决办法,这让我的客户和我都松了一口气。
下面是原因和解决方案。
函数“sa_GetBlue”和“sa_GetRed”返回了“Py_False”。在返回“Py_False”或“Py_True”之前,你需要增加存储这些值的变量的引用计数。否则,可能会导致解释器的内存状态出现问题;虽然不会立刻崩溃,但随时都有可能崩溃。在我的情况下,它是在处理了20000到50000个请求后崩溃的。
请查看下面的链接,以便更好地理解我想要解释的内容。
@doomster 和 @Omnifarious;感谢你们的评论和提供的指导。