Thread: Dynamic memory problem

  1. #1
    Registered User *Tom*'s Avatar
    Join Date
    Oct 2005
    Location
    England
    Posts
    7

    Unhappy Dynamic memory problem

    Hi, I'm trying to read in a text file and count the number of seperate words in each line of the file. The number of lines and the maximum line length is already known. The program compiles ok without any warnings, and it runs fine up untill the free(buffer) function where the program crashes and I get the message "DAMAGE: after Normal block (#45) at 0x00320A70". If I comment out the do-while loop then it runs right through to the end, so I'm assuming its the strtok() function thats causing the problem somehow, but I don't know why. Can anyone help?

    Code:
    	char *sep, *buffer;
    
    	buffer = (char*)malloc((MaxLineLen + 1)*sizeof(char));
    	i = 0;
    	do{
    		fgets(buffer,MaxLineLen, input);
    		buffer[strlen(buffer) - 1] = '\0';
    		//printf("%s\n", buffer);
    		sep = strtok(buffer, " ");
    		while(sep != NULL)
    		{
    			sep = strtok(NULL, " ");
    			WordsPerLine[i]++;
    		}
    		i++;
    	}while(i < LineCount);
    	free(buffer);

  2. #2
    Register User andor's Avatar
    Join Date
    Aug 2006
    Location
    Novi Sad
    Posts
    42
    I tried to compile your code and have bunch of errors. Post the whole code.

  3. #3
    Registered User *Tom*'s Avatar
    Join Date
    Oct 2005
    Location
    England
    Posts
    7
    This isn't the WHOLE code, but its enough to work. I just noticed after compiling this version that the WordsPerLine array never gets incremented even though the while loop appeared to be ok when i was stepping through it with the debugger.
    Code:
    #include<stdio.h>
    #include<stdlib.h>
    #include<conio.h>
    #include<string.h>
    
    int main(void)
    {
    	FILE *input;
    	char InName[] = {"input.txt"}, *buffer, *sep;
    	int c = 0, LineCount = 1, MaxLineLen = 0, i = 0;
    	int *WordsPerLine;
    
    	if((input = fopen(InName, "r")) == NULL)
    	{
    		printf("\t*** ERROR : the file '%s' was not opened ***\n\n\n", InName);
    		getch();
    		return 0;
    	}
    
    	while(c != EOF)	//calculate number of lines and max line length
    	{
    		c = getc(input);
    		i++;
    		if(c == 10 || c == 13)	//LF or CR
    		{
    			LineCount++;
    			MaxLineLen = i;
    			i = 0;
    		}
    	}
    	fclose(input);
    
    	WordsPerLine = (int*)malloc((LineCount + 1)*sizeof(int));
    	buffer = (char*)malloc((MaxLineLen + 1)*sizeof(char));
    	for(i=0;i<LineCount;i++)
    		WordsPerLine[i] = 0;
    
    	input = fopen(InName, "r");
    	i = 0;
    	do{
    		fgets(buffer,MaxLineLen, input);
    		buffer[strlen(buffer) - 1] = '\0';
    		sep = strtok(buffer, " ");
    		while(sep != NULL)
    		{
    			sep = strtok(NULL, " ");
    			WordsPerLine[i]++;
    		}
    		i++;
    	}while(i < LineCount);
    
    	for(i=0;i<LineCount;i++)
    		printf("Line %d : %d\n", (i+1), WordsPerLine[i]);
    	free(buffer);
    	free(WordsPerLine);
    	fclose(input);
    	getch();
    	return 0;
    }

  4. #4
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    If you already know how long the longest line is, you don't need to keep dynamically allocating space for the one line.
    Code:
    size_t wordsperline( char *s )
    {
        size_t wpl = 0;
    
        while( s && *s )
        {
            while( isspace( *s ) )
                s++;
            while( !isspace( *s ) )
                s++;
            wpl++;
        }
    
        return wpl;
    }
    
    ...
    
    int *wpls = NULL;
    size_t lines = 0;
    
    while( fgets( buf, BUFSIZ, fp )
    {
        int *p = realloc( wpl, (1 + lines) * sizeof *p  );
        if( p == NULL )
        {
            ...bad bad bad...
        }
        wpls = p;
        wpls[ lines++ ] = wordsperline( buf );
    }
    Good enough for who it's for.


    Quzah.
    Hope is the first step on the road to disappointment.

  5. #5
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Just a comment on your logic.

    An end of line is usually denoted by a CR/LF combo. Your code increments the linecount when it runs into EITHER of these char's. But there are TWO char's for every end of line, so your linecount in being incremented twice for each actual end of line.

    Why do all this to count words in a line of text? After the first letter in a sentence, every space (ascii 32), will indicate another word has been passed over, will it not?

    When a program runs, but then quits due to memory problems, you can be sure it's leaked or badly fragmented, memory. No doubt at all.

    Adak

  6. #6
    ATH0 quzah's Avatar
    Join Date
    Oct 2001
    Posts
    14,826
    Quote Originally Posted by Adak
    Just a comment on your logic.
    Whose logic? Try quoting whatever it is you're talking about. Remember a forum like this usually has more than one person replying. So when you say "you" or "your" without quoting, the reader assumes you're talking about the post directly above you.

    In which case...

    Try again. My function doesn't care about newline pairs. Furthermore, my OS doesn't use \n\r, and doesn't care anything about them. You must be using Windows. Finally, the standard input function fgets will handle this automatically when it reads a line.


    Quzah.
    Hope is the first step on the road to disappointment.

  7. #7
    Registered User *Tom*'s Avatar
    Join Date
    Oct 2005
    Location
    England
    Posts
    7
    Thanks for your help, I see what you mean about the LF/CR thing, but when I run the program it counts the correct number of lines. Can I rely on it to work for all windows xp machines?

    I have another question... is this the correct way to allocate and free memory for a 3 dimentional character array?

    Code:
    char ***words = NULL;
    
    //allocate memory
    
    words = (char***)malloc(NumberOfLines*sizeof(char**));
    for(i=0 ; i<NumberOfLines ; i++)
    	words[i] = (char**)malloc(WordsPerLine*sizeof(char*));
    for(i=0 ; i<NumberOfLines ; i++)
    	for(j=0 ; j<WordsPerLine ; j++)
    		words[i][j] = (char*)malloc((WordLength + 1)*sizeof(char));
    
    //free memory
    
    for(i=0 ; i<NumberOfLines ; i++)
    	for(j=0 ; j<WordsPerLine ; j++)
    		free(words[i][j]);
    for(i=0 ; i<NumberOfLines ; i++)
    	free(words[i]);
    free(words);

  8. #8
    Fountain of knowledge.
    Join Date
    May 2006
    Posts
    794
    No I don't think so
    Something more like:-

    words = (char***)malloc(rows*columns*height*sizeof(char));

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    /me horrified at all this malloc casting
    Read the FAQ people.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Mutex and Shared Memory Segment Questions.
    By MadDog in forum Linux Programming
    Replies: 14
    Last Post: 06-20-2010, 04:04 AM
  2. Why use Dynamic Memory
    By appleGuy in forum C++ Programming
    Replies: 11
    Last Post: 08-28-2006, 02:46 PM
  3. Help with a problem regarding dynamic memory and arrays
    By Michty in forum C++ Programming
    Replies: 5
    Last Post: 07-26-2006, 01:26 PM
  4. dynamic memory deletion via function
    By starkhorn in forum C++ Programming
    Replies: 4
    Last Post: 08-25-2004, 09:11 AM
  5. Memory Problem - I think...
    By Unregistered in forum C Programming
    Replies: 4
    Last Post: 10-24-2001, 12:14 PM