2010-08-19 9 views
9

मैंने SWIG के साथ एक PHP विस्तार बनाया है और सब कुछ ठीक काम करता है, लेकिन मैं विधि कॉल को चेन करते समय कुछ अजीब कचरा संग्रह व्यवहार देख रहा हूं। उदाहरण के लिए, इस काम करता है:संसाधन कचरा बहुत जल्दी

$results = $response->results(); 
$row = $results->get(0)->iterator()->next(); 
printf('%s %s' . "\n", $row->getString(0), $row->getString(1)); 

लेकिन इस SEG दोष:

$row = $response->results()->get(0)->iterator()->next(); 
printf('%s %s' . "\n", $row->getString(0), $row->getString(1)); 

फर्क सिर्फ इतना है कि पहले $results बनाता है, जबकि दूसरा चेन कॉल एक साथ है।

एसडब्ल्यूआईजी वास्तव में केवल PHP को फ़ंक्शंस का खुलासा करता है और उनके साथ बातचीत करने के लिए PHP प्रॉक्सी कक्षाएं उत्पन्न करता है। ये प्रॉक्सी कक्षाएं मूल रूप से एक संसाधन धारण करती हैं जो कि प्रत्येक कार्य को सामान्य रूप से ले जाने वाले अन्य तर्कों के साथ-साथ प्रकट किए गए कार्यों में से प्रत्येक को पास की जाती है। यह सोचकर कि शायद ये प्रॉक्सी कक्षाएं समस्या थीं, मैंने उन्हें बाईपास करने के लिए कोड को फिर से काम किया और इसके बजाय सीधे खुला कार्यों का उपयोग किया। पहले की तरह, इस काम करता है:

$results = InvocationResponse_results($response->_cPtr); 
$row = TableIterator_next(Table_iterator(Tables_get($results, 0))); 
printf('%s %s' . "\n", Row_getString($row, 0), Row_getString($row, 1)); 

और फिर, इस SEG दोष:

$row = TableIterator_next(Table_iterator(Tables_get(InvocationResponse_results($response->_cPtr), 0))); 
printf('%s %s' . "\n", Row_getString($row, 0), Row_getString($row, 1)); 

फिर, फर्क सिर्फ इतना है कि पहले $results बनाता है, जबकि दूसरा चेन कॉल एक साथ है।

इस बिंदु पर, मैंने gdb/valgrind में थोड़ी देर डिबगिंग बिताई और यह निर्धारित किया कि InvocationResponse_results रिटर्न के लिए विनाशक को कॉल करने पर बहुत जल्दी कॉल किया जाता है। निरीक्षण करने के लिए, मैंने खुला C++ फ़ंक्शंस और उनके विनाशकों के शीर्ष पर std::cout कथन डाले। यह चेन के बिना उत्पादन होता है:

InvocationResponse_results() 
Tables_get() 
Table_iterator() 
TableIterator_next() 
__wrap_delete_TableIterator 
Row_getString() 
Row_getString() 
Hola Mundo 
--- 
__wrap_delete_InvocationResponse 
__wrap_delete_Row 
__wrap_delete_Tables 

मैं स्क्रिप्ट के अंत में --- मुद्रित अंतर करने के लिए क्या स्क्रिप्ट के निष्पादन के दौरान होता है और क्या होता है सक्षम होने के लिए। Hola Mundoprintf से है। शेष सी ++ से है। जैसा कि आप देख सकते हैं, सबकुछ अपेक्षित क्रम में बुलाया जाता है। विनाशकों को केवल स्क्रिप्ट के निष्पादन के बाद बुलाया जाता है, हालांकि TableIterator विनाशक को पहले की अपेक्षा से पहले कहा जाता है। हालांकि, इससे कोई समस्या नहीं हुई है और संभवतः असंबंधित है। अब चेनिंग साथ उत्पादन करने के लिए इस तुलना:

InvocationResponse_results() 
Tables_get() 
__wrap_delete_Tables 
Table_iterator() 
TableIterator_next() 
__wrap_delete_TableIterator 
Row_getString() 
Segmentation fault (core dumped) 
बिना InvocationResponse_results के रिटर्न मान $results में सहेजा जा रहा है

, यह खुशी से पहले भी कॉल श्रृंखला से बाहर हैं और इस (Tables_get और Table_iterator के बीच) जल्दी हो जाता है निष्पादन कचरा एकत्र है सड़क के नीचे समस्याओं का कारण बनता है, अंततः एक सीजी गलती की ओर जाता है।

मैंने विभिन्न स्थानों पर xdebug_debug_zval() का उपयोग करके संदर्भ संख्या का भी निरीक्षण किया, लेकिन कुछ भी असामान्य नहीं पाया।

results: (refcount=1, is_ref=0)=resource(18) of type (_p_std__vectorT_voltdb__Table_t) 
row: (refcount=1, is_ref=0)=resource(21) of type (_p_voltdb__Row) 

और $row पर चेनिंग साथ:: यहाँ चेनिंग बिना $results और $row पर इसके उत्पादन है

row: (refcount=1, is_ref=0)=resource(21) of type (_p_voltdb__Row) 

मैं अब इस पर कुछ दिनों खर्च किया है और मैं सिर्फ विचारों से बाहर के बारे में हूँ , इसलिए वास्तव में इसे हल करने के बारे में कोई अंतर्दृष्टि की सराहना की जाएगी।

+0

यह बेहद असंभव है कि मानसिक डिबगिंग शक्तियों के बिना कोई भी इसे समझने में सक्षम होगा। मेरा सुझाव है कि आप '_zend_list_delete' में ब्रेकपॉइंट डाल दें और पता लगाएं कि कॉलिंग कोड संसाधन को क्यों हटा रहा है। यह 0 या सीधे हटाए जाने वाले संसाधन रिफ्रॉउंट हो सकता है। – Artefacto

+0

@Artefacto मैंने '_zend_list_delete' के अंदर peeked जबकि' __wrap_delete_Tables' को बुलाया जा रहा है और दोनों मामलों में (कोई सीईजी गलती और सीईजी गलती नहीं है), यह कचरा इकट्ठा किया गया है क्योंकि इसकी refcount ('--le-> refcount') -1 है। –

+0

तो पता लगाएं कि '__wrap_delete_Tables' को उस अवसर पर उस अवसर पर क्यों कहा जाता है, लेकिन दूसरे में नहीं और आगे बढ़ना जारी रखें। – Artefacto

उत्तर

1

This इसी तरह की डीबग समस्या segfaulting पर समस्या का हिस्सा बन गया। (क्या आर्टेफैक्टो ने कहा)

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