Why does malloc return NULL with lots of memory and always at the same point?

I am rather saddened by a mistake that I cannot overcome.

For my C programming class at university, I had to implement a parser for GML (Graph Modeling Language) input streams.

If successful, the parser returns the abstract data type to the caller, which is the adjacency matrix as a graph representation.

Well, the parser works flawlessly, there would be no problem that would reduce me to despair over the past few days. There is one function call in the parser, which in turn calls malloc. malloc is called quite often during a scanner that delivers a character to a character to the parser. But the malloc'd memory blocks are ALWAYS freed by calling free () before leaving the scan routine.

But inside the parser there is only one fatal function call, which, in turn, calls a function that uses malloc to reserve 12 bytes of memory (three integer properties) to save the structure. A structure is needed to store information about one edge in a graph (source node, target node, weight).

This call is made two times. for the first time everything is going well. Then, since there can be 1 to n edges according to the gml syntax, the code enters a while loop, where the same pointer is assigned a pointer to the new Edge Struct if there is Edges in the input stream. The first call of the Edge recognition procedure in the loop, which is the second in general (the first of them occurs before entering the loop, see Ma), is constantly interrupted by malloc, returning NULL.

I just have no idea why.

This is not a memory shortage problem, because when I mainall 1000 bytes in the main () function of this program, just for fun, it works fine.

I am using Code :: Blocks and DevCPP as an IDE. In both cases, the program faces the same problem.

Here is my basic parsing procedure:

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; } 

}

Here's GetNextSymbol (a scanner that supplies characters to the parser):

 /** * 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; } 

and now a fatal call in the Edge recognition routine. First, the title for the structure

 #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 

Implementation

 #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; } 

I know this is a lot of code;) Just to show that everything that can be freed, I freed.

I ran into my problem over the last two days, of course, also here, when the stack overflows, and there are hundreds of sites, messages, etc. about malloc returning null. They all say basically the same thing: not enough memory (that is, let's call it improbable) or a fragmented heap, so there are no memory blocks of sufficient size.

but: all I'm asking for is 12 (in words: twelve) bytes to store three int properties. which seems too big.

Have I exceeded some internal limits that I don't know about?

Help would be greatly appreciated.

Thanks in advance Roland

EDIT 2012-11-24:

thank you for your responses. but. The problem should be more basic.

because: when I tested other parts of my program (input / output file), etc., which are much less complicated than the parser, and go only one call in depth from main (), I also can not malloc. The file I am reading has approximately 140 bytes. Even when I test an I / O part that is isolated from all other parts, even when I pass them to third-party developers in another project, I do not get any memory from the system. in no way. I restarted the computer, that’s it. absolutely. not. change.

any ideas? at the same time, I spent too many hours on this project, most of which track these errors ... *** - (((

+6
source share
2 answers

If you suspect that you are using too much memory or fragmenting all available memory, you can check the memory usage of your application while it is running. If it eats all system memory, malloc returned NULL because of this.

If the above is not relevant to your case, I will check your application for heaps. Usually, when you rewrite heap structures, very bad things happen. In debug mode, the compiler adds some additional checks and red zones to detect heap corruption. In unlock mode, heap structures usually result in access violation. I can imagine that in very rare cases, heap structures can be damaged and damage can be interpreted as being out of space, so NULL is returned by malloc.

Somehow I would use a memory debugger. Valgrind has saved me many times, but it may not be available in your environment. There are many stackoverflow questions about memory debuggers.

+3
source

I cannot say much, only one observation. In GetNextSymbol() I see no limit on the number of digits read, so there is the possibility of a buffer overflow. The same goes for reading the identifier.

Another in Graph() , Edge(sourceString, currentPosition) failure Edge(sourceString, currentPosition) causes a while loop and the result is never freed, AFAICS.

+1
source

All Articles