C - Freeing Heap Memory Allocated in Another File - c

If you have a project that utilizes a makefile which compiles multiple files and headers, does this complicate the heap?
Specifically:
I have a main.c file which includes a header, say test.h. In test.c which is linked to test.h memory is allocated explicitly with malloc. main.ccalls the functions in test.c. For some reason, when I try to to free memory inside of the functions in test.c I always get an error:
main(65245) malloc: *** error for object 0x106d012f8: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
...this error occurs even though I never, not even once free any memory at all in the entire makefile stack. Obviously stdlib.h is included. What could be going on? Are there separate heaps for main.c and test.c and whenever the latter is called and the result is returned, the heap memory allocated is already freed? I'm really stumped. I can allocate and free memory in main.c without any issue. They have the same includes.

there is no such thing as 'different files' at run-time. all files are integrated into one big binary code at linkage. So, therefore, there is obviously only one heap.
your problem must be something else, since you never freed a memory, maybe you are trying to free static allocated memory or something like that
also, note that there is a convention which is usually pretty good to prevent memory leaks, which says: the part of the program that allocated the memory, is also responsible to free it. It is not directly connected to your question, but it will be helpful for future to try and do it, in order to prevent memory leaks.

Are you freeing the same addres/pointer in each file? Yes, you get 1 heap unless you specifically try and get multiple heaps. My guess is you are not freeing the same pointer - perhaps a addressing/double pointer error of some sort. You do best to post some source code for us to be sure...

All malloc() calls allocate from the same heap, no matter what file you call them from. You are freeing a pointer that did not come from any malloc() call.
Review your code carefully, print allocated and freed pointer values to debug log.

Related

Is there a way to find out if a pointer is okay to pass to free(), other than by calling free()?

First, a little background so you won't think I'm attempting to do something insane:
I'm trying to debug a crash in a C library that was written by someone else. The crash looks like this:
TheProgram(44365,0x7fff75996310) malloc: *** error for object 0x7fb8d4b9d440: pointer being freed was not allocated
The crash occurs on a system where I can't run valgrind, alas. The first thing I did was wrap debug-print-macros around all of the library's calls to malloc(), calloc(), realloc(), and free() so that I see printf() output whenever memory is allocated/reallocated/freed by the library. From that debug output, it appears that the pointer that makes free() crashing was indeed allocated previously in the program, and that it wasn't freed before the problem free() call:
JJ_CHECK_MALLOC at [fastgr.c : 265] malloc() returned 0x7fb8d4b9d440
[...]
JJ_CHECK_FREE at [dotinit.c : 204] about to call free(0x7fb8d4b9d440)
TheProgram(44365,0x7fff75996310) malloc: *** error for object 0x7fb8d4b9d440: pointer being freed was not allocated
So presumably what must be happening is that somewhere after the call to malloc() and before the call to free(), the heap must be getting corrupted in such a way that free() no longer thinks that that pointer is valid.
What I need to do, then, is track down the routine that is causing the heap corruption. One way I could do this is to query the validity of the pointer at various places along the execution path, and narrow down where its status changes from "valid heap pointer" to "the heap manager doesn't know what this pointer is". But the only way I know of to find out whether the heap manager thinks the pointer is free-able is to call free(), which I obviously can't do while the program still wants to use the pointer. Is there some way to call the check-if-pointer-is-in-heap function that free() uses, without actually freeing the data?
In general: No.
There are "debugging heaps" which surround allocated blocks with additional "fence" information to help detect bad-pointer errors. These will fairly reliably complain if you try to free something that wasn't allocated through them, since the fences will be missing. (They'll also complain if you've overwritten the end of the buffer and damaged the fence, of course.) In environments where code changed frequently, I've sometimes run with these heaps permanently enabled despite the performance costs... but one would hope that they could normally be turned off before the code ships to customers.

How are double frees detected in glibc?

* glibc detected ./load: double free or corruption (!prev): ADDRESS **
When using glibc, how does it know that I am double-freeing? Does it keep track of everything I malloced and freed? Is it contained in metadata like how free knows how much space to free (How does free know how much to free?)
For each allocation, memory manager keeps some 'header' (most likely tree node or linked list). When you passed to free something that doesn't contain valid header - well, it couldn't correctly be freed. As for where this information is being kept - it's up to implementation, but usually it placed right before address you got from malloc - however, size and structure is very likely to be unknown, but at least it gives an idea how easily this header could be broken/corrupted/overwritten/etc.
When you malloc something, you get a pointer on a memory bloc. You already know that ^^. The memory management also reserve an (hidden) header before* your bloc (which tracks the bloc size for instance)
When you free your pointer, the header is red to check if it is a valid pointer. The free operation also erase the header.
If you free twice, the header will no longer be valid on the second free. Hence the detection.
The C language standard says that freeing a pointer a second time is undefined behavior. What you see in glibc is one particular case of this undefined behavior--a helpful one--where a message is issued. Most allocators keep track of what is allocated and up to a certain amount it can keep track of what has been freed. But you cannot count on this behavior.
A C program is also allowed to silently crash or ignore the situation (or any other action it deems necessary).
The memory allocated by malloc(), calloc() or realloc() does have a metadata for the allocation, which is used by free() to de-allocate the allocated memory.
However, one should not make any assumptions about how or whether the double free is detected as the behavior is undefined in the standard as stated below.
free() frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.

How to handle free() errors in C?

Suppose that I have used a free() function to free a memory that,for many reasons, I'm not allowed to.
How can I stop my C application from crashing and just generate an error and continue the execution? I don't have try-catch kind of provision here (like C++/java...). Is there any way to ignore this error and continue execution?
If yes,
How do you do that?
More importantly, is it advisable to do so (continuing execution considering this memory error occurred)?
Thank you
It's certainly not advisable. Even if your program's version of free correctly detects that the memory you're trying to free cannot be freed, and thus doesn't do any harm itself, you still have a bug in your program — part of the program thought it owned that memory. Who knows what it might have tried to do with that memory before freeing it? Find and fix the bug. Don't just sweep it under the rug.
There is nothing in the C standard that you can use to do what you want. The description of the free function is very clear on that (§7.20.3.2 in C99):
The free function causes the space pointed to by ptr to be deallocated, that is, made
available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if
the argument does not match a pointer earlier returned by the calloc, malloc, or
realloc function, or if the space has been deallocated by a call to free or realloc,
the behavior is undefined.
Freeing invalid memory is a serious bug and should be fixed, as it's possible to corrupt the state of your program. Try using a tool like valgrind to spot what's going wrong.
The only pointers you should be using free on are those you receive from malloc, calloc or realloc or NULL pointers. Further you shouldn't use free on the same pointer more than once.

Allocating and freeing memory

My question is quite simple. We generally allocate memory by declaring a pointer and then assigning a block of memory to that pointer. Suppose somewhere in the code I happen to use
ptr = ptr + 1
and then I use
free(ptr)
can someone tell what will happen. The entire memory block will get deallocated or something else. Can I partially deallocate the memory?
You must always pass exactly the same pointer to free that you got from malloc (or realloc.) If you don't, the "behavior is undefined", which is a term of art that means you can't rely on the program behaving in any predictable way. In this case, though, you should expect it to crash immediately. (If you get unlucky, it will instead corrupt memory, causing a crash some time later, or worse, incorrect output.)
The only way to partially deallocate memory is realloc with a smaller size, but that's only good for trimming at the end and isn't guaranteed to make the trimmed-off chunk available for some other allocation.
It's impossible to deallocate part of a memory block. The only thing you can do is reallocate the block giving it a different size. However this does not guarantee that the block will land in the same place in memory (it might be copied somewhere else).
You must pass to free() the same pointer to the same location malloc() returned. That's because the allocator keeps a sort of list of the blocks you allocated (#everyone: feel free to add/modify if I'm wrong) and if the pointer you pass to free doesn't compare it this list free() complains ("bad memory block" maybe?). To partly deallocate the memory you should use realloc(), which changes the dimensions of that block of memory, but is slow and inefficient. You should use it only when you're sure of the new size of the block or leaving more space to fill in the future.
malloc() , free() and realloc() are not part of C language.
These are functions defines in standard library. Code in standard library that deals with it is usually called "allocator". So, actual answer is "It depends on C library".
On Linux, glibc would crash the program.
On VC++, C runtime would corrupt allocator's state
Source code is available for these libraries, so you can actually put a breakpoint and step into free.

Heap error in C

I know this is really general, but I get "this" (see below) when I run my .c file in Visual C++ 2008 Express. It happens when I call malloc (). Take my work on this - I dynamically allocate memory properly.
HEAP[Code.exe]: HEAP: Free Heap block 211a10 modified at 211af8 after it was freed
Windows has triggered a breakpoint in Code.exe.
This may be due to a corruption of the heap, which indicates a bug in Code.exe or any of the DLLs it has loaded.
This may also be due to the user pressing F12 while Code.exe has focus.
The output window may have more diagnostic information.
Why do I get this error? What does this even mean?
The error message tells you exactly why you got it:
Free Heap block 211a10 modified at 211af8 after it was freed
You had a heap allocated block that was freed then something wrote to that area of memory. It's not nice to write to a freed block of memory.
The error isn't actually happening when you call malloc; that's just when it triggers a free heap scan. The actual error happened somewhere before. You malloced some memory at address 211a10 (that's what malloc returned to you). Then you (or some other lib) freed it. Then later, when you call malloc in debug mode, it scans the whole heap -- as a courtesy to you, the poor programmer. It discovers that somebody (your or some lib you call) wrote over part of that array, specifically at address 211af8, or 0xe8 bytes into the array. So you're either still hanging onto a pointer that's been freed (most likely) and using it, or you're just trashing random memory.
In my case, with similar symptoms, the issue was the struct alignment mismatch (/Zp option)
I defined for my code a different struct alignment than external libraries (wxWidgets).
However, wxWidgets was built with the makefile, so it was compiled using the defaut /Zp.
And wxWidget is statically linked.
You can do that, but if you try to delete a wxWidgets-class object from your code the compiler becomes confused about the exact size of struct members.
And when running, you get this message:
HEAP[Code.exe]: HEAP: Free Heap block 211a10 modified at 211af8 after it was freed
Windows has triggered a breakpoint in Code.exe.
Solution:
Be sure to use the same "Struct Member Alignment" in all code and libraries.
Best rule is to define /ZP to use "default" value.
In Visual Studio, under Properties C/C++ Code Generation
MSDN cite: "You should not use this option unless you have specific alignment requirements."
See here
Tip: use #pragma pack if you need to control the alignment in some structs
See there
Example:
#pragma pack(1) // - 1 byte alignment
typedef union
{
u64 i;
struct{ // CUSTOMS.s is used by Folders
u32 uidx; // Id, as registered
byte isoS, isoT; // isoS/isoT combination.
byte udd0, udd1; // custom values (TBD)
}s;
}CUSTOMS;
struct Header // exactly 128 bits
{
u32 version;
u32 stamp; // creation time
CUSTOMS customs; // properties
}
#pragma pack() // this pragma restores the **default** alignment
*
Hope this explanation helps, because this is not actually a bug in code, but a serious configuration mistake: difficult to detect because it is located in subtle compiler options. Thanks for all,
*
I dynamically allocate memory properly.
I think that the problem here is that you unallocate the memory inproperly. What I mean by this is that, you might be trying to use freed memory. Sorry I can't help any further, you could probably add the actual code.
Take my work on this - I dynamically allocate memory properly.
But are you sure your buffers are all of the correct size and you free() them properly? Double frees and buffer overflows can easily lead to heap corruption that can cause malloc() to fail in all kind of ways.
If the management structures used internally by malloc() get damaged, it will usually not lead to an error immediately. But later calls to malloc() or free() that try to use these damaged structures will fail do erratic things.
Are you using malloc() on an array? Because I think the error just might be you forgetting to allocate an extra memory location at the end -- what happens is it tries to write to that location, which isn't allocated to it, and assumes it's trying to write to a place that has already been freed.

Resources