2012-11-17 40 views
6

मैं एक त्रुटि पर काफी हताश हूं, जिसे मैं खत्म नहीं कर पा रहा हूं।मॉलोक बहुत सारी मेमोरी के साथ न्यूल को वापस क्यों करता है और हमेशा एक ही बिंदु पर?

विश्वविद्यालय में मेरे सी प्रोग्रामिंग कक्षा के लिए, मुझे जीएमएल (ग्राफ मॉडलिंग भाषा) इनपुट स्ट्रीम के लिए एक पार्सर लागू करना पड़ा।

सफलता पर, पार्सर कॉलर को एक सार डेटाटाइप देता है, जो ग्राफ के प्रतिनिधित्व के रूप में एक एडजेंसी मैट्रिक्स है।

ठीक है, पार्सर बेकार ढंग से काम करता है, पिछले कुछ दिनों में मुझे निराशा के लिए मुझे कम करने में कोई समस्या नहीं होगी। पार्सर में, एक फ़ंक्शन कॉल होता है जो बदले में मॉलोक को कॉल करता है। स्कैनर के दौरान अक्सर मॉलोक को कॉलर के प्रतीक द्वारा प्रतीक प्रदान करता है। लेकिन malloc'd mem भाग हमेशा स्कैनर दिनचर्या छोड़ने से पहले मुक्त() को कॉल करके मुक्त कर दिया जाता है।

लेकिन पार्सर के अंदर काफी घातक फ़ंक्शन कॉल होता है, जो बदले में एक फ़ंक्शन को कॉल करता है जो एक स्ट्रक्चर को बचाने के लिए 12 बाइट मेमोरी (तीन पूर्णांक गुण) आरक्षित करने के लिए मॉलोक का उपयोग करता है। ग्राफ (स्रोत नोड, लक्ष्य नोड, वजन) के भीतर एक किनारे के बारे में जानकारी संग्रहीत करने के लिए संरचना की आवश्यकता है।

यह कॉल दो बार किया गया है। पहली बार, सब ठीक हो जाता है। फिर, जैसा कि जीएमएल सिंटैक्स के अनुसार 1 से एन किनारों तक हो सकता है, कोड थोड़ी देर लूप में प्रवेश करता है, जहां एक ही सूचक को एक नए एज स्ट्रक्चर में पॉइंटर के साथ असाइन किया जाता है, जब तक इनपुट स्ट्रीम में किनारों को पाया जाता है। लूप के भीतर एज पहचान दिनचर्या का पहला कॉल, जो कुल मिलाकर दूसरा होता है (पहला लूप दर्ज करने से पहले होता है, एमए देखें), लगातार मॉलोक लौटने से विफल रहता है।

मुझे बस इतना नहीं पता कि क्यों।

यह स्मृति की कमी के मुद्दे के बारे में नहीं है, क्योंकि जब मैं उस कार्यक्रम के मुख्य() फ़ंक्शन में 1000 बाइट्स को मॉल करता हूं, तो बस मज़े के लिए, यह ठीक काम करता है।

मैं आईडीई के रूप में कोड :: ब्लॉक और देवसीपीपी का उपयोग करता हूं। दोनों में, कार्यक्रम एक ही समस्या का सामना करता है।

Here's अपने मुख्य पार्स दिनचर्या:

DirectedGraph Graph(char* sourceString, int*currentPosition){ 

int sym; 
int restartPosition = 0; 
int* backupPosition; 
char* backupString; 
int nodeCount = 0; 

int currentSrc = -1; 
int currentTgt = -1; 
int currentWgt = -1; 
EdgeDescription e; 
DirectedGraph correctMatrix; 
MatrixStruct* errorMatrix = NULL; 

/*begin parsing*/ 
bool isGraphHeader = GraphHdr(sourceString, currentPosition); 

if(isGraphHeader == true){ 

    bool isNode = Node(sourceString, currentPosition); 

    if(isNode == true){ 

    while(isNode == true){ 

     nodeCount++; 
     restartPosition = *currentPosition; 
     isNode = Node(sourceString, currentPosition); 

    } 

    *currentPosition = restartPosition; 

    /*now get edge information (from-to-weight)*/ 
    /*as we have already read the next symbol, we have to reset*/ 
    /*our read position by one symbol backwards*/ 
    e = Edge(sourceString, &restartPosition); /*<======== HERE I CALL THE FATAL ROUTINE FOR THE FIRST TIME - EVERYTHING´s JUST FINE, PROGRAM PROCEEDS*/ 
    restartPosition = 0; 

    /*just for clearer coding in if statement*/ 
    currentSrc = e->source; 
    currentTgt = e->target; 
    currentWgt = e->weight; 
    destroyEdge(e); 

    if(currentSrc != -1 && currentTgt != -1 && currentWgt != -1){ 

     /*initialize matrix with counted number of nodes*/ 
     correctMatrix = CreateNewGraph(nodeCount); 

     /*the edge is inserted only when it lies within the boundaries*/ 
     /*of our graph. but we do not interrupt the whole processing, we just skip it.*/ 
     while(currentSrc != -1 && currentTgt != -1 && currentWgt != -1){ 

      if(currentSrc <= nodeCount && currentTgt <= nodeCount){ 

       InsertEdge(correctMatrix, currentSrc, currentTgt, currentWgt); 
       restartPosition = *currentPosition; 
      } 

      e = Edge(sourceString, currentPosition); /* <============== THIS IS THE CALL THAT FAILS*/ 
      currentSrc = e->source; 
      currentTgt = e->target; 
      currentWgt = e->weight; 

     } 

     /*as we have read over the next symbol in the loop, reset the position to read*/ 
     *currentPosition = *currentPosition - 1; 
     sym = GetNextSymbol(sourceString,currentPosition); 

     if(sym == rightBrace){ 

      sym = GetNextSymbol(sourceString, currentPosition); 

      if(sym == eot){ 

       return correctMatrix; 
      } 
      else{ 
       return errorMatrix; 
      } 
     } 
     else{ 
      return errorMatrix; 
     } 
    } 
    else{ 
     return errorMatrix; 
    } 
    } 
    else{ 
    return errorMatrix; 
    } 
} 
else{ 
    return errorMatrix; 
} 

}

यहाँ GetNextSymbol (स्कैनर, कि पार्सर के प्रतीकों बचाता है):

/** 
* DOCUMENTATION 
* ============================ 
* This is the main scanning function 
* which is used by the parser to recognize 
* terminal symbols and valid literals. 
* 
* RETURNS: the enum code for the recognized symbol. 
* or an error code, when invalid symbol encountered. 
*/ 

int GetNextSymbol(char* sourceString, int* currentPosition){ 


    int symbolCode; 
    int loopCounter = 0; 
    char* currentIdentifier = (char*)malloc(10); 
    char* currentNumber = (char*)malloc(10); 
    int identifierPosition = 0; 
    int numberPos = 0; 
    int numericVal = 0; 
    char currentChar; 

    currentChar = getNextChar(sourceString, currentPosition); 

    /*skip all blanks, empty chars, 
    linefeeds, carriage returns*/ 
    while(currentChar == ' ' 
     || currentChar == 11 
     || currentChar == 10 
     || currentChar == 13 
     || currentChar == '\t') 
    { 
     currentChar = getNextChar(sourceString, currentPosition); 
    } 

    /*=====================================*/ 
    /*Section 1: scan for terminal symbols */ 
    /*====================================*/ 

    if(currentChar == '['){ 
     symbolCode = leftBrace; 
    } 
    else if(currentChar == ']'){ 
     symbolCode = rightBrace; 
    } 

    /*=====================================*/ 
    /*Section 2: scan for valid literals */ 
    /*====================================*/ 

    else if(isdigit(currentChar)){ 

     /*here we calculate the numeric value of a number expression*/ 
     /*when calculated, we assign the numeric value to the symCode variable*/ 
     /*this works out because the values for a real symbol are always negative*/ 
     symbolCode = digit; 
     while(isdigit(currentChar)){ 

     currentNumber[numberPos] = currentChar; 
     currentChar = getNextChar(sourceString, currentPosition); 
     loopCounter++; 
     numberPos++; 
     } 

     currentNumber[numberPos] = '\0'; 
     numericVal = atoi(currentNumber); 
     symbolCode = numericVal; 

     /*when identifier or braces follow number without space: reset currentPos*/ 
     /*to the position of the previous char*/ 
     if(isalpha(currentChar)){ 
     *currentPosition = *currentPosition - loopCounter; 
     } 
     else if(currentChar == ']'){ 
     *currentPosition = *currentPosition - loopCounter; 
     } 
     else if(currentChar == '['){ 
     *currentPosition = *currentPosition - loopCounter; 
     } 

    } 
    else if(isalpha(currentChar)){ 

     while(isalpha(currentChar)){ 

     currentIdentifier[identifierPosition] = currentChar; 
     currentChar = getNextChar(sourceString, currentPosition); 
     loopCounter++; 
     identifierPosition++; 
     } 

     /*check wether we have found a valid identifying label*/ 
     /*and deallocate the reserved mem space*/ 
     currentIdentifier[identifierPosition] = '\0'; 
     symbolCode = recognizeIdentifier(currentIdentifier); 

     /*when number or braces follow identifier without space: reset currentPos*/ 
     /*to the position of the previous char*/ 
     if(isdigit(currentChar)){ 
     *currentPosition = *currentPosition - 1; 
     } 
     else if(currentChar == ']'){ 
     *currentPosition = *currentPosition - 1; 
     } 
     else if(currentChar == '['){ 
     *currentPosition = *currentPosition - 1; 
     } 

    } 
    else if(currentChar=='\0'){ 

     symbolCode = eot; 
    } 
    /*neither terminal symbol nor end of text found on current position --> illegal symbol*/ 
    else{ 
     symbolCode = error; 
    } 

    free(currentIdentifier); 
    free(currentNumber); 
    return symbolCode; 

} 

और अब "एज" मान्यता दिनचर्या में घातक कॉल। सबसे पहले, struct

#ifndef GML_EDGE_STRUCT_H_INCLUDED 
#define GML_EDGE_STRUCT_H_INCLUDED 


typedef struct EdgeStruct* EdgeObj; 

typedef struct EdgeStruct { 

    int source; 
    int target; 
    int weight; 

} EdgeStruct; 

typedef EdgeObj EdgeDescription; 

EdgeDescription createNewEdge(int src, int tgt, int wgt); 
void destroyEdge(EdgeObj); 

#endif // GML_EDGE_STRUCT_H_INCLUDED 

कार्यान्वयन

#include "GML_EDGE_STRUCT.h" 
#include <stdio.h> 
#include <stdlib.h> 
EdgeDescription createNewEdge(int source, int target, int weight){ 

    EdgeDescription e; 
    int bytesRequested = sizeof(EdgeStruct); 

    e = malloc(bytesRequested); 
    e->source = source; 
    e->target = target; 
    e->weight = weight; 
    return e; 
} 

मुझे पता है के लिए शीर्षक, काफी कोड यही;) बस दिखाने के लिए, कि जो कुछ भी मुक्त किया जा सकता, मैं मुक्त कर दिया।

मैंने पिछले दो दिनों से अपनी समस्या को हल किया, निश्चित रूप से यहां स्टैक ओवरफ़्लो पर भी, और वहां सैकड़ों साइटें हैं, पोस्टिंग और कैटर मॉलोक लौटने के बारे में बताती हैं। वे सभी मूल रूप से वही कहते हैं: पर्याप्त स्मृति नहीं (जो है, इसे असंभव रूप से कॉल करने दें), या खंडित ढेर, इसलिए पर्याप्त आकार के कोई ज्ञात भाग उपलब्ध नहीं हैं।

लेकिन: मैं सभी int गुणों को स्टोर करने के लिए 12 (शब्दों में: बारह) बाइट्स के लिए अनुरोध करता हूं। जो बहुत अधिक लगता है।

क्या मैंने कुछ आंतरिक सीमाएं पार कर ली हैं जिन्हें मैं नहीं जानता?

सहायता की सराहना की जाएगी।

अग्रिम रोलाण्ड

संपादित 2012-11-24 धन्यवाद: अपने जवाब के लिए

धन्यवाद। लेकिन। समस्या अधिक बुनियादी प्रकृति का होना चाहिए।

क्योंकि: जब मैंने अपने कार्यक्रम के अन्य हिस्सों (फ़ाइल I/O) इत्यादि का परीक्षण किया जो पार्सर से बहुत कम जटिल हैं और मुख्य() से केवल एक कॉल गहराई में जाते हैं, तो मैं भी malloc नहीं कर सकता। मैंने जो फ़ाइल पढ़ी है वह लगभग 140 बाइट्स है। यहां तक ​​कि जब मैं अन्य सभी भागों से पृथक I/O भाग का परीक्षण करता हूं, तब भी जब मैं उन्हें एक अलग प्रोजेक्ट में आउटसोर्स करता हूं, मुझे सिस्टम से कोई स्मृति नहीं मिलती है। किसी भी तरह से नहीं। मैंने कंप्यूटर को सब कुछ फिर से शुरू कर दिया है। पूर्ण रूप से। नहीं। परिवर्तन।

किसी भी विचार? इस दौरान इस परियोजना में मैंने बहुत अधिक घंटे लगाए हैं, जिनमें से अधिकतर उन f *** ing मेमोरी त्रुटियों को ट्रैक कर रहे हैं ...: - ((

+7

क्या आप सुनिश्चित हैं कि समस्या malloc वापस लौटने के बारे में है? यह बहुत दुर्लभ है, इसके बजाय ऐसा हो सकता है कि आप एक पॉइंटर मुक्त कर दें। जोर देने के लिए प्रयास करें कि मॉलोक कभी वापस नहीं लौटाता है। –

+7

क्या आपने वालग्रिंड की कोशिश की है? –

उत्तर

1

मैं ज्यादा नहीं कह सकता, बस एक अवलोकन। GetNextSymbol() में, मैं Graph() में अंकों की संख्या को पढ़ने पर कोई प्रतिबंध नहीं देखते हैं, तो वहाँ एक बफर अतिप्रवाह की संभावना है। एक ही एक पहचानकर्ता पढ़ने के लिए चला जाता है।

एक और एक, ऐसा न करने Edge(sourceString, currentPosition) कॉल एक में है जबकि लूप और परिणाम कभी मुक्त नहीं होता है, AFAICS।

3

यदि आपको संदेह है कि आप बहुत अधिक मेमोरी का उपयोग करने या सभी उपलब्ध स्मृति को खंडित करने के लिए आवेदन कर सकते हैं तो आप कर सकते हैं चलते समय अपने एप्लिकेशन द्वारा मेमोरी उपयोग की जांच करें। यदि यह सभी सिस्टम मेमोरी खाती है तो मैलोक इस वजह से NULL लौटा।

यदि उपरोक्त आपका मामला नहीं है तो मैं ढेर भ्रष्टाचार के लिए आपके आवेदन की जांच करूंगा। आम तौर पर जब आप ढेर संरचनाओं को ओवरराइट करते हैं तो बहुत बुरी चीजें होती हैं। डीबग मोड कंपाइलर में ढेर भ्रष्टाचार का पता लगाने के लिए कुछ अतिरिक्त चेक और लाल जोनों को जोड़ता है। रिहाई मोड में ब्रेकिंग ढेर संरचनाएं आम तौर पर उल्लंघन का उपयोग करती हैं। मैं कल्पना कर सकता हूं कि बहुत दुर्लभ मामलों में ढेर संरचनाओं को क्षतिग्रस्त किया जा सकता है और क्षति को अंतरिक्ष के बाहर के रूप में व्याख्या किया जा सकता है ताकि मॉलोक द्वारा न्यूल वापस किया जा सके।

एक तरफ या दूसरा मैं मेमोरी डीबगर को नियोजित करता हूं। Valgrind मुझे कई बार बचाया, लेकिन यह आपके पर्यावरण में उपलब्ध नहीं हो सकता है। मेमोरी डीबगर्स के बारे में स्टैक ओवरफ्लो पर यहां कई विषय हैं।