6

से लौटाया गया है हम Matlab कंपाइलर से बनाई गई लाइब्रेरी के साथ इंटरफेसिंग कर रहे हैं। हमारी समस्या लाइब्रेरी से लौटाई गई सरणी से संबंधित है।mxArray ऑब्जेक्ट्स पर mxDestroyArray को कॉल करना मैटलैब कंपाइलर रनटाइम

एक बार जब हम सरणी के साथ समाप्त हो जाते हैं, तो हम स्मृति को मुक्त करना चाहते हैं, हालांकि, ऐसा करने से कभी-कभी विभागीकरण दोष होते हैं।

यहाँ मैटलैब पुस्तकालय (bugtest.m) ::

यहाँ आदेश हम इसे बनाने के लिए इस्तेमाल किया है (, libbugtest.so बनाने और libbugtest.h) ::

mcc -v -W lib:libbugtest -T link:lib bugtest.m 

यहाँ हमारे सी है परीक्षण कार्यक्रम (bug_destroyarray.c) ::

#include <stdio.h> 
#include <stdlib.h> 

#include "mclmcrrt.h" 
#include "libbugtest.h" 

#define TESTS 15000 

int main(int argc, char **argv) 
{ 
    const char *opts[] = {"-nojvm", "-singleCompThread"}; 
    mclInitializeApplication(opts, 2); 
    libbugtestInitialize(); 

    mxArray *output; 
    mxArray *input; 
    double *data; 
    bool result; 
    int count; 

    for (count = 0; count < TESTS; count++) { 

     input = mxCreateDoubleMatrix(4, 1, mxREAL); 
     data = mxGetPr(input); data[0] = 0.5; data[1] = 0.2; data[2] = 0.2; data[3] = 0.1; 

     output = NULL; 
     result = mlfBugtest(1, &output, input); 
     if (result) { 
      /* HERE IS THE PROBLEMATIC LINE */ 
      /*mxDestroyArray(output);*/ 
     } 

     mxDestroyArray(input); 
    } 

    libbugtestTerminate(); 
    mclTerminateApplication(); 
} 

यहां कैसे हम सी कार्यक्रम (bug_destroyarray बनाने) ::

mbuild -v bug_destroyarray.c libbugtest.so 

हम मानते हैं कि mxDestroyArray(output) समस्याग्रस्त है संकलन है।

  • 32 क्लस्टर नोड्स के प्रत्येक पर:

    हम निम्नलिखित क्रैश होने का परीक्षण करने चलाते हैं।

  • रन bug_destroyarray
  • सेगमेंटेशन दोषों के लिए आउटपुट आउटपुट।

लगभग 10% समय दुर्घटनाग्रस्त है। यदि यह नोड्स में स्वतंत्र है तो आपको लगता है कि यह लगभग 0.3% समय क्रैश हो रहा है।

जब हम उस समस्याग्रस्त रेखा को निकालते हैं तो हम इसे क्रैश करने में असमर्थ होते हैं।

हालांकि इस लाइन को शामिल नहीं होने पर स्मृति उपयोग धीरे-धीरे बढ़ता है।

हमारे द्वारा किए गए शोध से, ऐसा लगता है कि हम वापस सरणी को नष्ट करने के लिए माना जाता है, अगर नहीं, तो हम स्मृति को लीक करने से कैसे रोक सकते हैं?

धन्यवाद।

+0

क्या आप वाकई 'mlfBugtest' सही का हस्ताक्षर है कर रहे हैं? प्रलेखन 'एमएलएफ'-फ़ंक्शंस रिटर्न' शून्य 'इंगित करता है, न कि' बूल '। – wakjah

उत्तर

0

कुछ नोट:

  • मैं mclInitializeApplication के लिए अनुमति दी विकल्पों की सूची में singleCompThread नहीं दिख रहा।

  • recommended तरीका है अपनी सी कार्यक्रम संकलित करने के लिए गतिशील रूप से संकलित पुस्तकालय के खिलाफ से जोड़ने के लिए है:

    mbuild -v -I. bug_destroyarray.c -L. -lbugtest 
    
  • अपने सी कार्यक्रम के शीर्ष पर, बस उत्पन्न हेडर फाइल में शामिल हैं, यह अन्य हेडर शामिल होंगे के बदले में।उत्पन्न हैडर को देख से, यह है:

    #pragma implementation "mclmcrrt.h" 
    #include "mclmcrrt.h" 
    

    मैं इस pragma लाइन का सही अर्थ नहीं जानता, लेकिन शायद यह जीसीसी compilers के साथ मायने रखती है ..

  • तथ्य यह है कि दोनों MLX/MLF उत्पन्न फ़ंक्शन रिटर्न बूलियन undocumented है। लेकिन हेडर फाइल को देखते हुए दोनों हस्ताक्षर वास्तव में वापसी करते एक bool:

    extern bool mlxBugtest(int nlhs, mxArray *plhs[], int nrhs, mxArray *prhs[]); 
    extern bool mlfBugtest(int nargout, mxArray** x, mxArray* y); 
    

मैं अपने कोड की कोशिश की और यह कोई segfaults साथ बस ठीक काम करता है। चूंकि मेरे पास कंप्यूटर के क्लस्टर तक पहुंच नहीं है, इसलिए मेरा परीक्षण केवल मेरी स्थानीय मशीन (R2013a के साथ WinXP) पर किया गया था।

मुझे इसे काम करने के लिए एमसीआर प्रारंभिक विकल्पों दोनों को हटाना पड़ा (विशेष रूप से nojvm रनटाइम त्रुटि उत्पन्न हुई)। मामूली संशोधन के साथ नीचे पूरा कोड है। इसे चलाने के लिए लगभग 10 सेकंड ले लिया:

#include <stdio.h> 
#include <stdlib.h> 
#include "libbugtest.h" 

#define TESTS 15000 

int main() 
{ 
    mxArray *output, *input; 
    double *data; 
    int count; 
    bool result; 

    if(!mclInitializeApplication(NULL,0)) { 
     fprintf(stderr, "Could not initialize the application.\n"); 
     return EXIT_FAILURE; 
    } 
    if (!libbugtestInitialize()) { 
     fprintf(stderr, "Could not initialize the library.\n"); 
     return EXIT_FAILURE; 
    } 

    for (count = 0; count < TESTS; count++) { 
     input = mxCreateDoubleMatrix(4, 1, mxREAL); 
     data = mxGetPr(input); 
     data[0] = 0.5; data[1] = 0.2; data[2] = 0.2; data[3] = 0.1; 

     output = NULL; 
     result = mlfBugtest(1, &output, input); 
     if (!result) { 
      fprintf(stderr, "call failed on count=%d\n", count); 
      return EXIT_FAILURE; 
     } 

     mxDestroyArray(output); output = NULL; 
     mxDestroyArray(input); input = NULL; 
    } 

    libbugtestTerminate(); 
    mclTerminateApplication(); 

    return EXIT_SUCCESS; 
} 

इसके अलावा संकलन कदम विंडोज पर थोड़ी अलग है, क्योंकि हम स्थिर आयात lib के खिलाफ लिंक (जो एक ठूंठ सम्मिलित करता है गतिशील रूप क्रम पर DLL लोड करने के लिए):

mbuild -v -I. bug_destroyarray.c libbugtest.lib 
0

विस्तृत उत्तर एमरो के लिए धन्यवाद।

हमने बिना किसी सफलता के अनुशंसित लोगों को हमारे संकलन चरणों को बदलने की कोशिश की।

निम्नलिखित तय हमारे SEG-दोषयुक्त समस्या:

  • प्रत्येक यात्रा पर output = NULL सेट न करें, बल्कि लूप के बाहर एक बार करते हैं।
  • लूप के अंदर mxDestroyArray(output) पर कॉल न करें, संदर्भ: here

हमारी गलतफहमी यह थी कि (ऐसा लगता है) आपको mxArray पॉइंटर्स का पुन: उपयोग करना होगा जो आप MATLAB फ़ंक्शन को पास करते हैं। यह चीजों को हमारे पक्ष में थोड़ा बोझिल बनाता है क्योंकि हमें इस सूचक का पुन: उपयोग करने की सावधानी बरतनी चाहिए।

हालांकि, स्मृति पूरी तरह स्थिर है, और तब से हमें कोई दुर्घटना नहीं हुई है।

+0

मुझे लगता है कि आप उस दूसरे बिंदु पर चीजों को भ्रमित कर रहे हैं। आपके द्वारा लिंक किया गया पृष्ठ एमएक्स-फ़ंक्शंस के संदर्भ में है (जहां आप बाएं हाथ की तरफ MATLAB पर वापस नहीं आना चाहते हैं)। दूसरी बात के लिए, [डॉक्स] (http://www.mathworks.com/help/compiler/matlab-compiler-generated-interface-functions.html#f2-1008549) स्पष्ट रूप से कहता है कि "अगर आउटपुट वेरिएबल्स आपको एक एमएलएफ फ़ंक्शन में पास न्यूल नहीं होते हैं, एमएलएफ फ़ंक्शन उन्हें mxDestroyArray का उपयोग करके मुक्त करने का प्रयास करेगा। " इसलिए कोई फर्क नहीं पड़ता कि क्या आप स्वयं को स्मृति को स्पष्ट रूप से मुक्त करते हैं या एमएलएफ फ़ंक्शन को – Amro

+0

आह ठीक है, स्पष्टीकरण के लिए धन्यवाद। मुझे कभी नहीं कहा जाना चाहिए था, सिर्फ लूप के अंदर नहीं था। यह सब अब समझ में आता है, और सही ढंग से काम कर रहा है। चीयर्स। – user2427155

1

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

एमरो सर्वाधिक प्रासंगिक जानकारी प्रदान करता है, लेकिन यह उनका विस्तार करना ... यदि आपके पास ' mxDestroyArray फ़ंक्शन को चीजों के रूप में कॉल करने के लिए कॉल करें, फिर आप स्मृति को रिसाव करेंगे, क्योंकि आपने NULL पर आउटपुट सेट किया है और इसलिए एमएलएफ फ़ंक्शन mxDestroyArray पर कॉल करने का प्रयास नहीं करेगा। इसका सारांश यह है कि यदि आपने mxDestroyArray कहा है और फिर एमएलएफ फ़ंक्शन और output कॉल करने का प्रयास नहीं किया गया है, तो एमएलएफ फ़ंक्शन mxDestroyArray को output पर कॉल करने का प्रयास करेगा। प्रश्न यह है कि output बिंदु क्या है? यह mxDestroyArray पर जाने के बाद output पर एक अंधेरे कोने का थोड़ा सा होता है। मैं कहूंगा कि यह एक अनचाहे धारणा है कि यह NULL पर सेट है; यह निश्चित रूप से दस्तावेज नहीं है कि mxDestroyArrayNULL पर इसका तर्क सेट करता है।इसलिए, मुझे संदेह है कि क्या हो रहा है यह है कि mxDestroyArray पर आपके कॉल के बीच और एमएलएफ फ़ंक्शन को फिर से निष्पादित करने वाला कोड, output द्वारा इंगित स्मृति को कुछ और आवंटित किया गया है और इसलिए आपका एमएलएफ फ़ंक्शन किसी और चीज़ से संबंधित स्मृति को मुक्त करने का प्रयास करता है। वोला, सीजी गलती। और निश्चित रूप से यह तभी होगा जब उस स्मृति को फिर से आवंटित किया गया हो। कभी-कभी आप भाग्यशाली हो जाएंगे, कभी-कभी नहीं।

सुनहरा नियम यह है कि यदि आप mxDestroyArray को फिर से उपयोग करने जा रहे किसी चीज़ के लिए कॉल कर रहे हैं, तो सूचक तुरंत NULL पर सेट करें। वैसे भी आपको वास्तव में अपने फ़ंक्शन के अंत में सामान को नष्ट करने की आवश्यकता है, क्योंकि आप सुरक्षित रूप से एमएलएफ कॉल में आउटपुट चर का पुनः उपयोग कर सकते हैं।

लड़का

+0

मेरी इच्छा है कि मैं इसके लिए एक अच्छा संदर्भ पा सकूं। सबसे अच्छा मैं पा सकता हूं [सी साझा पुस्तकालयों को एकीकृत करें] (http://www.mathworks.com/help/compiler/c-shared-library-target.html) –

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