Thread: (C, Malloc, Free) Help! Access violation and/or damage after normal block!!

  1. #1
    I typecast anyway.
    Join Date
    Jun 2005
    Posts
    25

    Unhappy (C, Malloc, Free) Help! Access violation and/or damage after normal block!!

    Hey, I'm writing a C program that uses a whole lot of malloc and free commands. I've run into a snag where partway through execution, it fails on a free command. However I've checked thoroughly by printing out memory addresses as they are allocated and freed, and this memory is allocated with malloc and used successfully before I attempt to use free on it.

    Luckilly I always used this to call free:
    Code:
    void safefree (void *pointer) {
    	
    	if (pointer) {
    
    #ifdef DEBUG
    		fprintf (debugOut, "%p: safefree\n", pointer);
    		fflush (debugOut);
    #endif
    
    		free (pointer);
    	}
    }
    So for debugging I just commented out the line: free (pointer);

    However, then I found out that the program was still hanging on free, but within the fflush command! And this time, as I'm writing this post, it's the printf command causing the problem. The problem is always in SubBlock_merge_prev, which is nested deep within the free command (nothing I have anything to do with).

    The call stack according to CodeWarrior (8.3) debugger:
    Code:
    0x77E8141A( kernel32.dll )
    mainCRTStartup
    main
    printf
    __pformatter
    __FileWrite
    fwrite
    __fwrite
    __flush_buffer
    __write_file
    __msl_write
    free
    __pool_free
    deallocate_from_fixed_pools
    deallocate_from_var_pools
    Block_link
    SubBlock_merge_prev
    I have a temporary fix, which is the following:
    Code:
    void free (void *ptr) {}
    However this makes the program eat a TON of memory.

    I tried using Visual Studio, and it no longer crashes if I comment the free line in safefree. So at least standard libraries aren't crashing there. However, with my free uncommented, I get "DAMAGE: after Normal block (#57) at 0x0032FC18." I'm not sure if this is Visual Studio's gentle way of telling me I'm freeing memory twice, but the space should be allocated correctly with malloc so I'm not sure what the problem is.

    Any ideas?

  2. #2
    .
    Join Date
    Nov 2003
    Posts
    307
    When you get mallopt or whatever exceptions on freeing a pointer it's usually because you
    iterated (++) (+=) (--) the pointer variable you used as a return from malloc.

    Most malloc's ( see this:
    http://www-106.ibm.com/developerwork...lnxw16InsideMe )

    keep what amounts to a descriptor exactly adjactent to the starting address of the memory block allocated. When you "move" the pointer and then free() it the descriptor isn't there -
    any kind of data in the buffer you malloc'ed is there.

    The descriptor on a 32 bit box would be a longword with the number of allocated bytes, followed by the actual first byte of the new buffer.

  3. #3
    Registered User mitakeet's Avatar
    Join Date
    Jun 2005
    Location
    Maryland, USA
    Posts
    212
    As jim said, this is typically a problem with buffer overruns and can happen ANYWHERE in your code, not just where the problem manifests (actually, usually far away from the crash location). You may find my writup on memory bounds violations useful: http://sol-biotech.com/code/BufferOverflows.html.

    Free code: http://sol-biotech.com/code/.

    It is not that old programmers are any smarter or code better, it is just that they have made the same stupid mistake so many times that it is second nature to fix it.
    --Me, I just made it up

    The reasonable man adapts himself to the world; the unreasonable one persists in trying to adapt the world to himself. Therefore, all progress depends on the unreasonable man.
    --George Bernard Shaw

  4. #4
    I typecast anyway.
    Join Date
    Jun 2005
    Posts
    25

    Unhappy

    Ah... I started suspecting it wasn't that particular buffer when commenting out the free statement gave me errors in the free statements that are inside fflush and printf. Plus it's a pretty straightforward string deallocation that it's stopping on, no pointer arithmetic was done to that space. So I guess something else is messing up the data that free looks at.

    Sounds like it could be tricky to find this problem. Hopefully with the help of my debuggers I'll get it eventually. Thanks both of you!

    Btw, anyone with other ideas or suggestions can still post too, in case there's something we might have missed.

  5. #5
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    You can try something like valgrind or electricfence which do a pretty excellent job at tracking down misuse of dynamic memory allocation. I'm not sure if there are Windows ports of them though.
    If you understand what you're doing, you're not learning anything.

  6. #6
    Frequently Quite Prolix dwks's Avatar
    Join Date
    Apr 2005
    Location
    Canada
    Posts
    8,057
    After you free the pointer, try setting it to NULL, so that the next time your free function is called, it won't be freed.

    Post your code.

  7. #7
    Registered User
    Join Date
    Mar 2005
    Posts
    36
    The above should be enough, but if this is really bad and hard to find you can set up a queue to store malloced addresses, have "safemalloc" put address in the queue, have "safefree" remove it, and if its trying to free something not in the queue, spit out a msg (and continue). You can hang on the badfree msg with a debugger to find out more.

    You are most likely trying to free a modified pointer in the case you describe, as McNamara described, or just directly changed to point somewhere else.

  8. #8
    I typecast anyway.
    Join Date
    Jun 2005
    Posts
    25

    Talking Fixed it!! I think.

    I think I fixed it!

    I have a function that copies a string to a new size, and I was using it with strlen (oldStr) to copy strings down to the minimum size needed. Unfortunately, my malloc was missing a +1 needed to hold the null terminator.

    The code:
    Code:
    char *expandString (char *oldStr, unsigned int newSize, unsigned char freeOld) {
    
    	char *newStr;
    	
    	// Allocate the larger space and copy the string.
    	newStr = (char *) malloc (newSize + 1);  // THIS WAS MISSING +1 BEFORE
    	
    	strcpy (newStr, oldStr);
    	
    	// If the old pointer will now point to this new string, free old space.
    	// Do not free the old string if a pointer will still be using it.
    	if (freeOld)
    		safefree (oldStr);
    	
    	// Return pointer to new string.
    	return newStr;
    }
    It runs just fine in both my compilers now. Thanks for your help everyone! It did turn out to be overflow (off by 1).

    BTW, the reason I didn't post the whole program is because it's pretty big... For code I have written, I have one main file with 263 lines, a file with code that will be shared among similar programs with 421 lines, and 3 files with pretty general-purpose code (such as expandString) at 63 lines, 114 lines, and 168 lines.
    Last edited by Raptor007; 06-23-2005 at 06:38 PM. Reason: Additional information.

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    > void safefree (void *pointer)
    You have if ( pointer ) free ( pointer )
    but free itself doesn't mind being called with NULL, and this function does nothing to protect you from doing something dumb like

    char arr[10];
    char *p = arr;
    safefree( p );
    Will still blow up within free() despite your defences.

    > newStr = (char *) malloc (newSize + 1); // THIS WAS MISSING +1 BEFORE
    Lose the cast - see the FAQ.
    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.

  10. #10
    I typecast anyway.
    Join Date
    Jun 2005
    Posts
    25
    Well, my idea behind safefree was originally this:
    Code:
    void safefree (void **pointerPointer) {
    	
    	if (*pointerPointer) {
    
    		free (*pointerPointer);
    		*pointerPointer = NULL;
    	}
    }
    But it was too much of a hassle calling free with:
    Code:
    safefree ((void **) &pointer);  // My compiler needs this cast.
    So I use the safefree that I posted previously and call it with:
    Code:
    safefree (pointer);
    pointer = NULL;
    Doesn't catch everything, but it has the potential to help, and if I'm debugging it makes it easy to print out the addresses I free by enclosing all calls to free in my safefree function.

    By the way, I read the FAQ on casting, and I saw no compelling arguements either way. Maybe it's not needed, but I like to have them there so when I look at code a long time after I write it, it's easier to remember what each allocation is for.
    Last edited by Raptor007; 06-24-2005 at 11:30 AM.

  11. #11
    Gawking at stupidity
    Join Date
    Jul 2004
    Location
    Oregon, USA
    Posts
    3,218
    By the way, I read the FAQ on casting, and I saw no compelling arguements either way. Maybe it's not needed, but I like to have them there so when I look at code a long time after I write it, it's easier to remember what each allocation is for.
    I suppose you find this kind of casting useful too since it's basically the same thing?
    Code:
    int foo(void)  { return 5; }
    
    {
      int a;
    
      a = (int)foo();
    }
    You can see what it's for at a later date by just seeing what type of variable you're assigning the memory pointer to.
    If you understand what you're doing, you're not learning anything.

  12. #12
    I typecast anyway.
    Join Date
    Jun 2005
    Posts
    25
    In your example, no, I wouldn't use casting. I use casting when void * (or void **, void ***, etc) are involved. It's especially useful when lots of code separates the declarations from the actual use of the variable.

    For example, with something like this:
    Code:
    void *Vector_getElement (struct Vector *vec, int index);
    
    int main () {
        struct MyType *element;
    
        ...
    
        element = (struct MyType *) Vector_getElement (myVec, 0);
    }
    ...I would use the casting to make it more clear, especially if ... represents a lot of code.

    But anyway, I posted here about a malloc/free issue that's been resolved (thanks again everyone!), not casting. My casting is working fine, and I consider it a purely stylistic decision.
    Last edited by Raptor007; 06-24-2005 at 04:22 PM. Reason: Oops, can't post to thread about casting, it's locked.

  13. #13
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,660
    Well good luck with finding more obscure bugs of your own making is all I can add to that.
    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. Access violation... can't figure it out...
    By Raigne in forum C++ Programming
    Replies: 7
    Last Post: 10-11-2007, 10:52 AM
  2. HUGE fps jump
    By DavidP in forum Game Programming
    Replies: 23
    Last Post: 07-01-2004, 10:36 AM
  3. Pointer's
    By xlordt in forum C Programming
    Replies: 13
    Last Post: 10-14-2003, 02:15 PM
  4. gluBuild2DMipmaps & access violation
    By glUser3f in forum Game Programming
    Replies: 2
    Last Post: 10-03-2003, 02:31 PM
  5. Manipulating the Windows Clipboard
    By Johno in forum Windows Programming
    Replies: 2
    Last Post: 10-01-2002, 09:37 AM