Thread: glibc detected malloc(): memory corruption

  1. #1
    Registered User
    Join Date
    Nov 2008
    Posts
    19

    glibc detected malloc(): memory corruption

    I am getting the error: "glibc detected malloc(): memory corruption: 0xb7fd3008" when function int ** load_table(FILE * file, int size) starts under UNIX. It works nicely under Windows. Do you find any mistakes here in load_table function?

    Code:
    #include "mathalizer.h"
    
    int multiply(int x, int y)
    {
        return x*y;
    }
    
    int add(int x, int y)
    {
        return x+y;
    }
    
    int ** create_table(int size, int (* oper) (int,int))
    {
        int x; 
        int y; 
        int **array;
        if(size<1) return NULL;
        array = (int **)malloc(size*sizeof(int*));
        if(array==NULL) return 1;
    
        for(x=0;x<size;x++)
        {
            array[x]=(int*)malloc(size*sizeof(int));
        }
        
        for(x=0;x<size;x++) 
        {
            for(y=0;y<size;y++)
            {
                array[x][y]=(* oper)(x,y);
            }      
        }
    	
        return array;
    }
    
    int save_table(FILE * fp, int ** array, int size)
    {
        int x;
        
        for(x=0;x<size;x++)
        {
            fwrite(array[x],sizeof(int),size,fp);     
        }
        fclose (fp);
       
        return 1;        
    }
    
    int ** load_table(FILE * file, int size)
    {
        int x;
        int fread_return_code_2;
        int **array2;
        array2 = (int **)malloc(size*sizeof(int*));
        if(array2==NULL) return 1;
    
        for(x=0;x<size;x++)
        {
            array2[x]=(int*)malloc(size*sizeof(int));
        }
    	
        for(x=0;x<size;x++)
        {
            fread_return_code_2=fread(array2[x],sizeof(int),size,file);
        }
        if(fread_return_code_2!=size) return 1;
        fclose(file);
    	
        return array2;
    }

  2. #2
    Registered User
    Join Date
    Oct 2008
    Location
    TX
    Posts
    2,059
    Can you post the code that calls load_table() as there doesn't seem to be anything wrong with it so maybe the way it's called may have something to do with it.

  3. #3
    Registered User
    Join Date
    Nov 2008
    Posts
    19
    That's the testing program:

    Code:
    int main(int argc, char ** argv) {
    
    	/* check save & load */
    	check_saveload(10);
    //	check_saveload(100);
    
    	return EXIT_SUCCESS;
    }
    Code:
    int check_saveload(int size) {
    	FILE * tfile;
    	int ** table;
    	int fsize, i, j;
    
    	if((tfile = tmpfile() ) == NULL) {
    		perror("test_saveload");
    		return 0;
    	}
    
    	table = create_table(size, multiply);
    	if(!table) {
    		fprintf(stderr, "test_saveload: Table was NULL\n");
    		return 0;
    	}
    	
    	if ((save_table(tfile, table, size)) != 1) {
    		fprintf(stderr, "test_saveload: Unable to save\n");
    		return 0;
    	}
    	/*		
    	destroy_table(table);
    	rewind(tfile);
    	if ((fsize = get_table_size(tfile)) != size) {
    		fprintf(stderr, "test_saveload: Table size was not %d\n", size);
    		return 0;
    	}*/
    	if ((table = load_table(tfile, size)) == NULL ) {
    		fprintf(stderr, "test_saveload: Got NULL in stead of table\n");
    		return 0;
    	}
    
    	for( i = 0; i < size; i++) {
    		for (j = 0; j < size; j++ ) {
    			if(table[i][j] != i*j) {
    				fprintf(stderr, "test_saveload: Multiplication error %d*%d is %d\n", i, j, table[i][j]);
    				return 0;
    			}
    		}
    	}
    	close(tfile);
    	destroy_table(table);
    	
    }
    Last edited by totalnewbie; 01-12-2009 at 12:33 AM.

  4. #4
    Registered User
    Join Date
    Jan 2008
    Posts
    290
    Following the flow of your program, you are first calling save_table(), and if that succeeds then you are calling load_table(). Unfortunately, during the call to save_table() you are closing the file. How are you expecting to read from a file that you've already closed?
    Code:
    int check_saveload(int size)
    {
       ...
       if ((save_table(tfile, table, size)) != 1)
       {
          fprintf(stderr, "test_saveload: Unable to save\n");
          return 0;
       }
    
       if ((table = load_table(tfile, size)) == NULL)
       {
          fprintf(stderr, "test_saveload: Got NULL in stead of table\n");
          return 0;
       }
       ...
    }
    
    int save_table(FILE * fp, int ** array, int size)
    {
        int x;
        
        for(x=0;x<size;x++)
        {
            fwrite(array[x],sizeof(int),size,fp);     
        }
        fclose (fp);
       
        return 1;        
    }
    
    int ** load_table(FILE * file, int size)
    {
        int x;
        int fread_return_code_2;
        int **array2;
        array2 = (int **)malloc(size*sizeof(int*));
        if(array2==NULL) return 1;
    
        for(x=0;x<size;x++)
        {
            array2[x]=(int*)malloc(size*sizeof(int));
        }
    	
        for(x=0;x<size;x++)
        {
            fread_return_code_2=fread(array2[x],sizeof(int),size,file);
        }
        if(fread_return_code_2!=size) return 1;
        fclose(file);
    	
        return array2;
    }
    I should also mention that you have a potential memory leak in your load_table() function:
    Code:
    int ** load_table(FILE * file, int size)
    {
        int x;
        int fread_return_code_2;
        int **array2;
        array2 = (int **)malloc(size*sizeof(int*));
        if(array2==NULL) return 1;
    
        for(x=0;x<size;x++)
        {
            array2[x]=(int*)malloc(size*sizeof(int));
        }
    	
        for(x=0;x<size;x++)
        {
            fread_return_code_2=fread(array2[x],sizeof(int),size,file);
            // You probably want to return as soon as you discover
            // that one of the reads failed (instead of continuing to loop)
            // However, you are forgetting to free the memory you allocated
            // for array2!
        }
        if(fread_return_code_2!=size) return 1;
        fclose(file);
    	
        return array2;
    }
    The functions save_table() and load_table() have no business closing the FILE* that they've been passed. Their jobs are to save the table to the given file, and load the table from the given file - nothing more. When you call fprintf() and pass it a FILE*, would you expect it to close the file for you? Hell no.

    I also noticed that you have a destroy_table() function that you didn't provide. The curious part is that you aren't passing it anything more than the table (int**). How does the destroy_table() function know how many rows there are in your table? It NEEDS to know that because you have to loop through and free each row before you free the array of row pointers. In other words:
    Code:
    void destroy_table(int **array, int size)
    {
      int i;
    
      for (i = 0; i < size; i++)
        free(array[i]);
    
      free(array);
    }
    And finally, and perhaps most importantly, COMPILE YOUR PROGRAMS WITH WARNINGS ENABLED. You have all sorts of minor issues in your program that should be throwing warnings. Returning ints from a function that should be returning a pointer (without casting), allowing control flow to reach the end of a non-void function, etc... If you really are a total newbie, this may be the most important thing you learn for a while. It also might not be a bad idea to learn how to use gdb to debug your programs. Proper use of a debugger can save you HOURS of time.

    (to enable warnings with gcc compile using the -Wall flag)

  5. #5
    Registered User Maz's Avatar
    Join Date
    Nov 2005
    Location
    Finland
    Posts
    194
    glibc detected... Sounds like you're running this on linux. Try running your program under valgrind, it should detect memory errors like this, and the location where that occurs. Just compile your source with debuginfos enabled (Eg. with flag -ggdb for example [ gcc -ggdb -o exeName file1.c file2.c )

  6. #6
    Registered User
    Join Date
    Nov 2008
    Posts
    19
    arpsmack, thank you so much! It works greatly now.
    Why is it necessary to release memory two times:
    free(array[i]);
    free(array);
    I thought that free(array[0]) is the same as free(array).

  7. #7
    Woof, woof! zacs7's Avatar
    Join Date
    Mar 2007
    Location
    Australia
    Posts
    3,459
    > I thought that free(array[0]) is the same as free(array).
    Not in this case.

    Remember you've allocated room for i pointers. You've also allocated memory which each respective pointer points to. Think of it like this;
    Code:
    int * array1;
    int * array2;
    int * array3;
    
    /* ... */
    array1 = malloc(sizeof(int));
    array2 = malloc(sizeof(int));
    array3 = malloc(sizeof(int));
    Plus an array to put all of the array_'s in. And sticking to the 1 malloc(), 1 free() rule... there you have it

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. glibc detected - error
    By mr_m4x in forum C Programming
    Replies: 2
    Last Post: 03-15-2009, 10:29 AM
  2. Replies: 7
    Last Post: 02-06-2009, 12:27 PM
  3. *** glibc detected *** a.out: realloc()
    By msshapira in forum C Programming
    Replies: 9
    Last Post: 01-27-2009, 09:49 AM
  4. Strange memory corruption
    By kwyjibo in forum C Programming
    Replies: 5
    Last Post: 10-29-2008, 03:59 AM
  5. *** glibc detected *** free(): invalid next size
    By icebabe in forum C Programming
    Replies: 2
    Last Post: 05-24-2006, 12:09 PM