2010-04-18 25 views
39

मैं अजगर विज्ञापन से सी एक्सटेंशन विकसित कर रहा हूं, मुझे कुछ segfaults (विकास के दौरान अपरिहार्य ...) प्राप्त होता है।पायथन एक विभाजन गलती का पता लगाने

मैं सेगफॉल्ट होता है (कोड एक कोड की प्रत्येक पंक्ति का पता लगाने की तरह है) पर प्रदर्शित करने के लिए एक तरीका खोज रहा हूं, मैं यह कैसे कर सकता हूं?

उत्तर

32

यहाँ उत्पादन के लिए एक रास्ता अपने कोड चलाता है अजगर के हर लाइन का फ़ाइल नाम और लाइन नंबर है:

import sys 

def trace(frame, event, arg): 
    print "%s, %s:%d" % (event, frame.f_code.co_filename, frame.f_lineno) 
    return trace 

def test(): 
    print "Line 8" 
    print "Line 9" 

sys.settrace(trace) 
test() 

आउटपुट:

call, test.py:7 
line, test.py:8 
Line 8 
line, test.py:9 
Line 9 
return, test.py:9 

(आप शायद पता लगाने उत्पादन लिखना चाहते हैं चाहते हैं एक फ़ाइल, निश्चित रूप से करने के लिए।)

+0

क्या यह सी एक्सटेंशन के साथ काम करता है? –

+1

@MadPhysicist: यदि आपका मतलब यह है कि यह आपके सी कोड की लाइन संख्या प्रिंट नहीं करेगा। :-) यह पाइथन कोड की लाइन संख्या मुद्रित करेगा जो आपके सी कोड में कॉल करता है। – RichieHindle

+0

यही मेरा मतलब था। मैंने मूल प्रश्न दिलचस्प पाया क्योंकि मुझे एक ही समस्या थी। Segfault इसलिए हो गया क्योंकि मेरा सी कोड एक पूर्ण तत्व को एक PyList_Object में डालने वाला था। जब मैंने सूची में पुनरावृत्ति करने की कोशिश की तो यह खुद पाइथन पक्ष पर प्रकट हुआ। सुनिश्चित नहीं है कि एक पायथन डीबगर उस मामले में बहुत मदद करेगा। –

54

आप लिनक्स पर कर रहे हैं, को चलाने gdb के तहत अजगर

gdb python 
(gdb) run /path/to/script.py 
## wait for segfault ## 
(gdb) backtrace 
## stack trace of the c code 
+7

यदि आपके पास पहले से कोर फ़ाइल है, तो आप 'gdb पायथन कोर' (या जो भी मूल फ़ाइल कहा जाता है) का उपयोग कर सकते हैं। यदि आप ओएसएक्स पर हैं, कोर डंप (डिफ़ॉल्ट रूप से जेनरेट नहीं किया गया; देखें 'ulimit -c') निर्देशिका'/cores' में संग्रहीत हैं। –

+0

मैं वास्तव में चाहता हूं कि यह मेरे लिए पहला जवाब था क्योंकि अन्य सभी को पढ़ने में काफी समय लगा, बल्कि मैंने अपनी बग को चलाने में बिताया था। – sage

+0

यदि आपको पाइथन यूनिट परीक्षण चलाने के दौरान एक segfault मिलता है जैसे 'python -m unittest my.module.tests.mytest', तो '-m' स्विच' gdb' को भ्रमित करता है। इस प्रकार '--args' विकल्प का उपयोग करके आमंत्रित करें: 'gdb --args python -m unittest my.module.tests.mytest' –

15

सी एक्सटेंशन से सेगफाल्ट अक्सर किसी ऑब्जेक्ट का नया संदर्भ बनाते समय संदर्भ गणना में वृद्धि नहीं करने का परिणाम होता है। इससे उन्हें ट्रैक करना बहुत मुश्किल हो जाता है क्योंकि ऑब्जेक्ट से अंतिम संदर्भ हटा दिए जाने के बाद सेगफॉल्ट होता है, और तब भी अक्सर जब किसी अन्य ऑब्जेक्ट को आवंटित किया जाता है।

आप यह नहीं कहते कि आपने अब तक कितना सी एक्सटेंशन कोड लिखा है, लेकिन यदि आप अभी यह शुरू कर रहे हैं कि आप या तो सीटीपीएस या Cython का उपयोग कर सकते हैं या नहीं। Ctypes आपकी आवश्यकताओं के लिए पर्याप्त लचीला नहीं हो सकता है, लेकिन आप सिथॉन के साथ किसी भी सी लाइब्रेरी से लिंक करने में सक्षम होना चाहिए और आपके लिए सभी संदर्भ संख्या स्वचालित रूप से बनाए रखी जानी चाहिए।

यह हमेशा पर्याप्त नहीं होता है: यदि आपके पायथन ऑब्जेक्ट्स और किसी अंतर्निहित सी ऑब्जेक्ट्स में अलग-अलग जीवनकाल होते हैं तो भी आपको समस्याएं मिल सकती हैं, लेकिन यह चीजों को काफी सरल बनाती है।

+2

इसके अलावा, उन स्थानों पर जहां NULL को शामिल नहीं किया जाता है। –

3

जीडीबी के लिए कुछ हद तक अनियंत्रित पायथन एक्सटेंशन हैं।

पायथन स्रोत से Tools/gdb/libpython.py (इसे सामान्य इंस्टॉल में शामिल नहीं किया गया है) से।

sys.path

तो में इस रखो:

# gdb /gps/python2.7_x64/bin/python coredump 
... 
Core was generated by `/usr/bin/python script.py'. 
Program terminated with signal 11, Segmentation fault. 
#0 call_function (oparg=<optimized out>, pp_stack=0x7f9084d15dc0) at Python/ceval.c:4037 
... 
(gdb) python 
>import libpython 
> 
>end 
(gdb) bt 
#0 call_function (oparg=<optimized out>, pp_stack=0x7f9084d15dc0) at Python/ceval.c:4037 
#1 PyEval_EvalFrameEx ([email protected]= 
    Frame 0x7f9084d20ad0, 
    for file /usr/lib/python2.7/site-packages/librabbitmq/__init__.py, line 220, 
    in drain_events (self=<Connection(channels={1: <Channel(channel_id=1, connection=<...>, is_open=True, connect_timeout=4, _default_channel=<....(truncated), [email protected]=0) at Python/ceval.c:2681 
... 
(gdb) py-list 
218   else: 
219    timeout = float(timeout) 
>220   self._basic_recv(timeout) 
221 
222  def channel(self, channel_id=None): 

आप देख सकते हैं अब हम अजगर ढेर CPython कॉल चेन के साथ इसी होते हैं।

कुछ चेतावनियां:

  • gdb का संस्करण 7 से अधिक होने की जरूरत है और यह (libpython से लिंक करके) --with-python
  • gdb साथ संकलित किया गया है की जरूरत है अजगर को एम्बेड करता है, यह नहीं चलता है यह एक सबहेल में। इसका अर्थ यह है कि यह आवश्यक रूप से पाइथन के संस्करण से मेल नहीं खा सकता है जो $PATH पर है।
  • आपको libpython.py को पाइथन स्रोत के किसी भी संस्करण से डाउनलोड करने की आवश्यकता है जो gdb से मेल खाता है।
  • आपको gdb को रूट के रूप में चलाने की आवश्यकता हो सकती है - यदि ऐसा है तो आपको डिबगिंग कोड के मिलान के लिए sys.path सेट अप करने की आवश्यकता हो सकती है।

आप sys.path में libpython.py कॉपी नहीं कर सकते हैं तो आप इस तरह यह स्थान है जोड़ सकते हैं sys.path रहे हैं:

(gdb) python 
>import sys 
>sys.path.append('/path/to/containing/dir/') 
>import libpython 
> 
>end 

यह कुछ हद तक खराब python dev docs, the fedora wiki और the python wiki

में प्रलेखित है यदि आपके पास एक पुराना gdb या सिर्फ यह काम नहीं कर सकता है पाइथन स्रोत में gdbinit भी है जिसे आप ~/.gdbinit w पर कॉपी कर सकते हैं इसमें कुछ समान कार्यक्षमता

0

मैं यहां एक ही समस्या का समाधान ढूंढ रहा था, और अन्य उत्तरों में से कोई भी मेरी मदद नहीं करता था। faulthandler में सहायता क्या थी, और आप इसे पाइथन 2.7 में इंस्टॉल कर सकते हैं बस pip install का उपयोग कर सकते हैं।

faulthandler केवल संस्करण 3.3 में पायथन के साथ पेश किया गया था, जिसे सितंबर 2012 में जारी किया गया था, जो कि यहां के अधिकांश अन्य उत्तरों के बाद लिखा गया था।

संबंधित मुद्दे