segmentation fault - core dump in python C-extension -
i writing c-extension python. can see below, aim of code calculate euclidean-dist of 2 vectors. first param n dimension of vectors, second , third param 2 list of float.
i call function in python this:
import cutil cutil.c_euclidean_dist(2,[1.0,1,0],[0,0])
and worked well, return right result. if more 100 times(the dimension 1*1000), cause segmentation fault - core dump:
#!/usr/bin/env python #coding:utf-8 import cutil import science import time = [] b = [] d = 0.0 x in range(2500): a.append([float(i+x) in range(1000)]) b.append([float(i-x) in range(1000)]) t1 = time.time() x in range(500): d += cutil.c_euclidean_dist(1000,a[x],b[x]) print time.time() - t1 print d
the c code here:
#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 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 python"); }
the error msg:
segmentation fault - core dump:
the c-extension compiled cutil.so, not know how see dump. looked through c code many times,and can not find problem..
may a memory problem?
it should simple piece of c code, what's wrong it? need help~ lot !
here result of 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> free software: free change , redistribute it. there no warranty, extent permitted law. type "show copying" , "show warranty" details. gdb configured "x86_64-linux-gnu". type "show configuration" configuration details. bug reporting instructions, please see: <http://www.gnu.org/software/gdb/bugs/>. find gdb manual , other documentation resources online at: <http://www.gnu.org/software/gdb/documentation/>. help, type "help". type "apropos word" search commands related "word"... reading symbols /usr/bin/python2.7...reading symbols /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 generated `python py.py'. program terminated signal sigsegv, segmentation fault. #0 0x00000000005398b3 in list_dealloc.16846 (op=0x7f688b2faa28) @ ../objects/listobject.c:309 309 ../objects/listobject.c: no such file or directory #0 0x00000000005398b3 in list_dealloc.16846 (op=0x7f688b2faa28) @ ../objects/listobject.c:309 #1 0x00000000004fdb96 in insertdict_by_entry (value=<optimized out>, ep=0x1777fa8, hash=<optimized out>, key='b', mp=0x7f68a8dbb168) @ ../objects/dictobject.c:519 #2 insertdict (value=<optimized out>, hash=<optimized out>, key='b', mp=0x7f68a8dbb168) @ ../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 @ remote 0x4480b30>, '__builtins__': <module @ remote 0x7f68a8de6b08>, 'science': <module @ remote 0x7f68a8ce4088>, '__package__': none, 'i': 999, 'cutil': <module @ remote 0x7f68a8cdfbb0>, 'time': <module @ remote 0x7f68a640ea28>, '__name__': '__main__', 't1': <float @ remote 0xd012708>, '__doc__': none}) @ ../objects/dictobject.c:765 #4 pydict_setitem ( op=op@entry={'a': none, 'x': none, 'c': none, 'b': none, 'd': <float @ remote 0x4480b30>, '__builtins__': <module @ remote 0x7f68a8de6b08>, 'science': <module @ remote 0x7f68a8ce4088>, '__package__': none, 'i': 999, 'cutil': <module @ remote 0x7f68a8cdfbb0>, 'time': <module @ remote 0x7f68a640ea28>, '__name__': '__main__', 't1': <float @ remote 0xd012708>, '__doc__': none}, key=key@entry='b', value=<optimized out>) @ ../objects/dictobject.c:818 #5 0x000000000055a9e1 in _pymodule_clear (m=<optimized out>) @ ../objects/moduleobject.c:139 #6 0x00000000004f2ad4 in pyimport_cleanup () @ ../python/import.c:473 #7 0x000000000042fa89 in py_finalize () @ ../python/pythonrun.c:459 #8 0x000000000046ac10 in py_main (argc=<optimized out>, argv=0x7fff3958d058) @ ../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) @ libc-start.c:287 #10 0x000000000057497e in _start ()
edit: comment last 2 sentences near last return:
py_decref(seq_a); py_decref(seq_b);
and seems work well. feel very strange... purpose of 2 sentence free(or release) 2 pyobject, why works without 2 sentences think necessary?
the c-extension compiled cutil.so, not know how see dump.
to solve this, i'm going cite gnu radio's gdb/python debugging mini-tutorial:
luckily, there's feature called core dumping allows state of program stored in file, allowing later analysis. usually, feature disabled; can enable by:
ulimit -c unlimited
note works processes spawned shell used ulimit in. happens here maximum size of core dump set unlimited (the original value 0 in cases).
now, core dump file lays in current execution directory of program crashed. in our case, that's build/python/, since core dumps should have name core., can use little find magic:
marcus> find -type f -cmin 5 -name 'core.[0-9]*'
./build/python/core.22608
because find _f_iles, changed/created within last _5 min_utes, having name matches.
using gdb core dump
having found build/python/core.22608, can launch gdb:
gdb programname coredump
i.e.
gdb /usr/bin/python2 build/python/core.22608
a lot of information might scroll by.
at end, you're greeted gdb prompt:
(gdb)
getting backtrace
typically, you'd backtrace (or shorter, bt). backtrace hierarchy of functions called.
(gdb)bt
[...] skipped,
frame #2 , following they're part of python implementation -- sounds bad, because gdb doesn't know how debug python, luckily, there's extension that. can try use py-bt:
(gdb) py-bt
if undefined command error, must stop here , make sure python development package installed (python-devel on redhatoids, python2.7-dev on debianoids); systems, should append content of /usr/share/doc/{python-devel,python2.7-dev}/gdbinit[.gz] ~/.gdbinit, , re-start gdb.
the output of py-bt states python lines correspond stack frame (skipping stack frames hidden python, because in external libraries or python-implementation routines)
...
Comments
Post a Comment