2011-04-01 12 views
7

मेरे पास एक सी-एक्सटेंशन शामिल है जिसमें मैं विकसित कर रहा हूं। सी में, मेरे पास A नामक युगल की एक सरणी है और AnotherIntVariable नामक एक इंट वैरिएबल है जिसे मैं पाइथन पास करना चाहता हूं। खैर, मेरी सी विस्तार मॉड्यूल में मैं निम्न कार्य करें:पायथन में सी-एक्सटेंशन - वापसी Py_BuildValue() मेमोरी लीक समस्या

int i; 
PyObject *lst = PyList_New(len_A); 
PyObject *num; 
if(!lst) 
    return NULL; 
for(i=0;i<len_A;i++){ 
    num=PyFloat_FromDouble(A[i]); 
    if(!num){ 
     Py_DECREF(lst); 
     return NuLL; 
    } 
    PyList_SET_ITEM(lst,i,num); 
} 
free(A); 
return Py_BuildValue("Oi",lst,AnotherIntVariable) 

तो अजगर में मैं इस सूची को और इस तरह पूर्णांक प्राप्त:

Pyt_A,Pyt_int=MyCModule.MyCFunction(...) 

कहाँ Pyt_A और Pyt_int सूची और पूर्णांक हैं मैं अपने सी-एक्सटेंशन "MyCModule" से मिलता हूं, जो कि पहले वर्णित "MyCFunction" फ़ंक्शन से मिलता है।

समस्या

कि, पायथन में, मैं इस Pyt_A सरणी का उपयोग करें (ताकि कारण है कि मैं एक साधारण return बयान के बजाय Py_BuildValue उपयोग करते हैं, आदेश कचरा कलेक्टर से एक पल के लिए इस चर को बचाने के लिए एक INCREF करना है), लेकिन है तो मुझे उस आवंटित स्मृति को मुक्त करने के लिए इसे किसी भी तरह से खराब करने की आवश्यकता है। समस्या यह है कि मैं कई बार MyCFunction फ़ंक्शन का उपयोग करता हूं, और यह एक स्मृति रिसाव उत्पन्न करता है क्योंकि मुझे पता नहीं है कि इससे छुटकारा पाने के लिए मुझे अजगर में प्राप्त सरणी को कैसे हटाया जाए।

मैं सिर्फ Py_BuildValue("Oi",lst,AnotherIntVariable) के बजाय कोड के सी हिस्से में एक return lst करके सरणी लौटने की कोशिश की, लेकिन एक विभाजन दोष में है कि केवल परिणाम जब मैं अजगर में इसका इस्तेमाल करने की कोशिश (शायद इसलिए कि कचरा कलेक्टर किया उसके काम) ...

... मुझे यहां क्या याद आ रही है? कोई भी मेरी मदद कर सकता हैं?

+0

पाइथन DECREF में डेल Pyt_A नहीं है और इसे हटा दें? – highBandWidth

+0

मैंने कोशिश की लेकिन यह काम नहीं कर रहा है। मुझे अभी भी यह स्मृति रिसाव मिल रहा है जिसके बारे में मैं बात कर रहा हूं। –

+1

इसके अलावा, आपके पास Py_BuildValue ("ओई", lst, anotherIntVariable) से पहले वापसी है? – highBandWidth

उत्तर

11

आप Py_BuildValue (http://docs.python.org/3/c-api/arg.html#c.Py_BuildValue) के लिए दस्तावेज़ को देखो आप देख सकते हैं O typecode के तहत है, यह कहना है कि की वस्तु में पारित द्वारा एक (नोट वृद्धि की जाती है संदर्भ गिनती: उस पृष्ठ में पहले खंड बताता है OPyArg_ParseTuple के लिए टाइपकोड, जो संदर्भ संख्या में वृद्धि नहीं करता है, लेकिन यहां भी प्रासंगिक नहीं है)।

तो, Py_BuildValue पर कॉल करने के बाद, आपकी सूची के लिए refcount 2 है, लेकिन आप केवल 1 होना चाहते हैं।

इसके बजाय सीधे Py_BuildValue का परिणाम लौटने, यह एक PyObject सूचक को बचाने के

,, lst संदर्भ गिनती घटती है तो अपने परिणाम लौटने।

आप Py_BuildValue कॉल का परिणाम जाँच की जानी चाहिए वैसे भी, जब से तुम भी घटना है कि Py_BuildValue विफल रहता में num मुक्त करने के लिए (अर्थात रिटर्न NULL) की जरूरत है।

+0

प्रलेखन अब कहता है _ "ऑब्जेक्ट की संदर्भ संख्या में वृद्धि नहीं हुई है" _ - तो यह कौन है? – Eric

+1

'Py_BuildValue' के लिए लक्ष्य लिंक एंकर बदल गया, इसलिए लिंक पृष्ठ के शीर्ष पर जा रहा था, जिसमें 'PyArg_ParseTuple' प्रारूप कोड शामिल हैं। मैंने लिंक तय किया, और संभावित भ्रमित प्रविष्टि के बारे में एक नोट जोड़ा। – ncoghlan

2

इग्नासिओ को साफ़ करने के लिए धन्यवाद, अब यह बहुत समझ में आता है! अंत में, हल करने के लिए, सीधे Py_BuildValue लौटने की बजाय,

free(A); 
PyObject *MyResult = Py_BuildValue("Oi",lst,AnotherIntVariable); 
Py_DECREF(lst); 
return MyResult 

यह एक आकर्षण की तरह काम करता था!

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