我是一个为Python编写c扩展的程序员。如下所示,代码的目的是计算两个向量之间的欧几里得距离。 第一个参数n是向量的维度, 第二个和第三个参数是两个浮点数列表。
在Python中,我这样调用函数:
import cutil
cutil.c_euclidean_dist(2,[1.0,1,0],[0,0])
它能够良好地工作并返回正确的结果。但是,如果我对其执行超过100次(尺寸为1 * 1000),它将导致分段错误 - 核心转储:
#!/usr/bin/env python
#coding:utf-8
import cutil
import science
import time
a = []
b = []
d = 0.0
for x in range(2500):
a.append([float(i+x) for i in range(1000)])
b.append([float(i-x) for i in range(1000)])
t1 = time.time()
for x in range(500):
d += cutil.c_euclidean_dist(1000,a[x],b[x])
print time.time() - t1
print d
以下是C代码:
#include <python2.7/Python.h>
#include <math.h>
static PyObject* cutil_euclidean_dist(PyObject* self, PyObject* args) {
PyObject *seq_a, *seq_b;
int n;
float * array_a,* array_b;
PyObject *item;
PyArg_ParseTuple(args,"iOO", &n , &seq_a, &seq_b);
if (!PySequence_Check(seq_a) || !PySequence_Check(seq_b)) {
PyErr_SetString(PyExc_TypeError, "expected sequence");
return NULL;
}
array_a =(float *)malloc(sizeof(float)*n);
array_b =(float *)malloc(sizeof(float)*n);
if (NULL == array_a || NULL == array_b){
PyErr_SetString(PyExc_TypeError, "malloc failed!");
Py_DECREF(seq_a);
Py_DECREF(seq_b);
return NULL;
}
int i;
for(i=0;i<n;i++){
item = PySequence_GetItem(seq_a,i);
if (!PyFloat_Check(item)) {
free(array_a); /* free up the memory before leaving */
free(array_b);
Py_DECREF(seq_a);
Py_DECREF(seq_b);
Py_DECREF(item);
PyErr_SetString(PyExc_TypeError, "expected sequence of float");
return NULL;
}
array_a[i] = PyFloat_AsDouble(item);
Py_DECREF(item);
item = PySequence_GetItem(seq_b,i);
if(!PyFloat_Check(item)) {
free(array_a);
free(array_b);
Py_DECREF(seq_a);
Py_DECREF(seq_b);
Py_DECREF(item);
PyErr_SetString(PyExc_TypeError, "expected sequence of float");
return NULL;
}
array_b[i] = PyFloat_AsDouble(item);
Py_DECREF(item);
}
double sum = 0;
for(i=0;i<n;i++){
double delta = array_a[i] - array_b[i];
sum += delta * delta;
}
free(array_a);
free(array_b);
Py_DECREF(seq_a);
Py_DECREF(seq_b);
return Py_BuildValue("d",sqrt(sum));
}
static PyMethodDef cutil_methods[] = {
{"c_euclidean_dist",(PyCFunction)cutil_euclidean_dist,METH_VARARGS,NULL},
{NULL,NULL,0,NULL}
};
PyMODINIT_FUNC initcutil(void) {
Py_InitModule3("cutil", cutil_methods, "liurui's c extension for python");
}
错误信息:
segmentation fault - core dump:
c扩展编译成了cutil.so,我不知道如何查看转储。
但是我已经仔细检查了我的C代码很多次,没有发现任何问题...
可能是内存问题吗?
这应该是一段非常简单的C代码,出了什么问题呢?我需要你的帮助~非常感谢!
这是gdb /usr/bin/python2.7 ./core的结果:
root@ubuntu:/home/rrg/workspace/opencvTest/test# gdb /usr/bin/python2.7 ./core
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.2) 7.7.1
Copyright (C) 2014 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from /usr/bin/python2.7...Reading symbols from /usr/lib/debug//usr/bin/python2.7...done.
done.
warning: core file may not match specified executable file.
[New LWP 13787]
[New LWP 13789]
[New LWP 13790]
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".
Core was generated by `python py.py'.
Program terminated with signal SIGSEGV, Segmentation fault.
#0 0x00000000005398b3 in list_dealloc.16846 (op=0x7f688b2faa28) at ../Objects/listobject.c:309
309 ../Objects/listobject.c: no such file or directory
#0 0x00000000005398b3 in list_dealloc.16846 (op=0x7f688b2faa28) at ../Objects/listobject.c:309
#1 0x00000000004fdb96 in insertdict_by_entry (value=<optimized out>, ep=0x1777fa8, hash=<optimized out>, key='b', mp=0x7f68a8dbb168) at ../Objects/dictobject.c:519
#2 insertdict (value=<optimized out>, hash=<optimized out>, key='b', mp=0x7f68a8dbb168) at ../Objects/dictobject.c:556
#3 dict_set_item_by_hash_or_entry (value=<optimized out>, ep=0x0, hash=<optimized out>, key='b',
op={'a': None, 'x': None, 'c': None, 'b': None, 'd': <float at remote 0x4480b30>, '__builtins__': <module at remote 0x7f68a8de6b08>, 'science': <module at remote 0x7f68a8ce4088>, '__package__': None, 'i': 999, 'cutil': <module at remote 0x7f68a8cdfbb0>, 'time': <module at remote 0x7f68a640ea28>, '__name__': '__main__', 't1': <float at remote 0xd012708>, '__doc__': None}) at ../Objects/dictobject.c:765
#4 PyDict_SetItem (
op=op@entry={'a': None, 'x': None, 'c': None, 'b': None, 'd': <float at remote 0x4480b30>, '__builtins__': <module at remote 0x7f68a8de6b08>, 'science': <module at remote 0x7f68a8ce4088>, '__package__': None, 'i': 999, 'cutil': <module at remote 0x7f68a8cdfbb0>, 'time': <module at remote 0x7f68a640ea28>, '__name__': '__main__', 't1': <float at remote 0xd012708>, '__doc__': None}, key=key@entry='b',
value=<optimized out>) at ../Objects/dictobject.c:818
#5 0x000000000055a9e1 in _PyModule_Clear (m=<optimized out>) at ../Objects/moduleobject.c:139
#6 0x00000000004f2ad4 in PyImport_Cleanup () at ../Python/import.c:473
#7 0x000000000042fa89 in Py_Finalize () at ../Python/pythonrun.c:459
#8 0x000000000046ac10 in Py_Main (argc=<optimized out>, argv=0x7fff3958d058) at ../Modules/main.c:665
#9 0x00007f68a8665ec5 in __libc_start_main (main=0x46ac3f <main>, argc=2, argv=0x7fff3958d058, init=<optimized out>, fini=<optimized out>, rtld_fini=<optimized out>, stack_end=0x7fff3958d048)
at libc-start.c:287
#10 0x000000000057497e in _start ()
抱歉,我无法理解您的请求。请提供需要翻译的具体内容。
Py_DECREF(seq_a);
Py_DECREF(seq_b);
然后它似乎运行得很好。我感到非常奇怪......这两个句子的目的是释放两个PyObject,为什么不加这两个句子也能正常工作呢?
malloc()
的返回值,如果其中一个malloc()
成功,则在if (NULL == array_a || NULL == array_b)
中会有内存泄漏。 - Iharob Al Asimi