Why freed struct in C still has data?
When I run this code:
#include <stdio.h>
typedef struct _Food
{
char name [128];
} Food;
int
main (int argc, char **argv)
{
Food *food;
food = (Food*) malloc (sizeof (Food));
snprintf (food->name, 128, "%s", "Corn");
free (food);
printf ("%d\n", sizeof *food);
printf ("%s\n", food->name);
}
开发者_如何学运维I still get
128
Corn
although I have freed food. Why is this? Is memory really freed?
When you free 'food', you are saying you are done with it. However, the pointer food still points to the same address, and that data is still there (it would be too much overhead to have to zero out every bit of memory that's freed when not necessary)
Basically it's because it's such a small example that this works. If any other malloc calls were in between the free and the print statements, there's a chance that you wouldn't be seeing this, and would most likely crash in some awful way. You shouldn't rely on this behavior.
There is nothing like free food :) When you "free" something, it means that the same space is again ready to be used by something else. It does NOT mean filling it up by garbage. Secondly, the pointer value has not changed -- if you are seriously coding you should set a pointer to NULL once you have freed it so that potential junk accesses like this do not happen.
Freeing memory doesn't necessarily overwrite the contents of it.
sizeof
is a compile-time operation, so memory allocation won't change how it works.
free
does not erase memory, it just marks the block as unused. Even if you allocate a few hundred megabytes of memory, your pointer may still not be overwritten (modern computers have lots of RAM). However, after you free memory, you can no longer depend on its value.
See if your development environment has a memory allocation debugging setting -- some have settings to overwrite blocks with something like 0xDEADBEEF
when you free
them.
Also, you may wish to adopt the habit of setting your pointer to NULL
immediately after calling free
(to help encourage your program to crash early and loudly).
free
tells the memory allocator that it can reuse that memory block, nothing else. It doesn't overwrite the block with zeros or anything - luckily, because that could be quite an expensive operation! What it does do is make any further dereferencing of the pointer undefined, but 'undefined' behaviour can very well mean 'do the same thing as before' - you just can't rely on it. In another compiler, another runime, or under other conditions it might throw an exception, or terminate the program, or corrupt other data, so... just DON'T.
There's no such thing as "struct has data" or "struct doesn't have data" in C. In your program you have a pointer that points somewhere in memory. As long as this memory belongs to your application (i.e. not returned to the system) it will always contain something. That "something" might be total garbage, or it might look more or less meaningful. Moreover, memory might contain garbage that appears as something meaningful (remains of the data previously stored there).
This is exactly what you observe in your experiment. Once you deallocated the struct, the memory formerly occupied by it officially contains garbage. However, that garbage might still resemble bits and pieces of the original data stored in that struct object at the moment it was deallocated. In your case you got lucky, so the data looks intact. Don't count on it though - next time it might get totally destroyed.
As far as C language is concerned, what you are doing constitutes undefined behavior. You are not allowed to check whether a deallocated struct "has data" or not. The "why" question you are asking does not really exist in the realm of C language.
In some systems freeing memory will unmap it from the address space and you will get a core dump or equivalent if you try to access it after unallocating it.
In win32 systems (at least up through XP) this is specifically not the case. Microsoft made their memory subsystem on 32 bit Windows purposely linger memory blocks to maintain compatibility with well known MS-DOS applications that used memory after freeing it.
In the MS-DOS programming model there is no concept of mapping or process space so these types of bugs didn't show up as program failures until they were executed as DOS-mode programs under Windows95.
That behavior persisted for 32-bit Windows for over a decade. It may change now that legacy compatibility is being withdrawn in systems such as Vista and 7.
精彩评论