Problem with free() on structs in C. It doesn't reduce memory usage?

Your answer is right over here on Stack Overflow but the short version is that, for very good reasons, the memory allocator does not return memory to the host OS but keeps it (internally in your program's data space) as a free list of some kind.

Up vote 7 down vote favorite share g+ share fb share tw.

I'm having a problem with free() on a struct in my C program. When I look at /proc//statm before and after the free it doesn't seem to reduce. Am I using free() wrong in this case, or am I reading /proc//statm wrong?

Here is a test case which yields the problem: struct mystruct { unsigned int arr10000; }; void mem() { char buf30; snprintf(buf, 30, "/proc/%u/statm", (unsigned)getpid()); FILE* pf = fopen(buf, "r"); if (pf) { unsigned size; // total program size unsigned resident;// resident set size unsigned share;// shared pages unsigned text;// text (code) unsigned lib;// library unsigned data;// data/stack unsigned dt;// dirty pages (unused in Linux 2.6) fscanf(pf, "%u %u %u %u %u %u", &size, &resident, &share, &text, &lib, &data); printf("Memory usage: Data = %d\n", data*sysconf(_SC_PAGESIZE)); } fclose(pf); } int main(int argc, char **argv) { mem(); struct mystruct *foo = (struct mystruct *)malloc(sizeof(struct mystruct)); mem(); free(foo); mem(); } The output is: Memory usage: Data = 278528 Memory usage: Data = 282624 Memory usage: Data = 282624 When I would expect it to be: Memory usage: Data = 278528 Memory usage: Data = 282624 Memory usage: Data = 278528 I've done a similar test with malloc'ing a (char *), then free'ing it and it works fine. Is there something special about structs? C memory-management struct malloc free link|improve this question asked May 14 '11 at 23:05oprimus805 75% accept rate.

Virtual memory is not a scarce resource and each process has its own address space anyway. – David Schwartz Aug 28 '11 at 11:55.

Your answer is right over here on Stack Overflow, but the short version is that, for very good reasons, the memory allocator does not return memory to the host OS but keeps it (internally in your program's data space) as a free list of some kind. Some of the reasons the library keeps the memory are: Interacting with the kernel is much slower than simply executing library code The benefit would be small. Most programs have a steady-state or increasing memory footprint, so the time spent analyzing the heap looking for returnable memory would be completely wasted.

Internal fragmentation makes page-aligned blocks (the only thing that could be returned to the kernel) unlikely to exist, another reason not to slow the program down looking for something that won't be there. Returning a page embedded in a free block would fragment the low and high parts of the block on either side of the page. The few programs that do return large amounts of memory are likely to bypass malloc() and simply allocate and free pages anyway using mmap(2).

Thanks. That answers my question. So I am free'ing it correctly, and I am reading /proc//statm correctly.

– oprimus May 15 '11 at 0:47 Oh, right, yes your code all looks correct, but your OS transaction will never show the image size decreasing unless some library function unrelated to malloc/free (like dlopen) uses mmap to release something. – DigitalRoss May 15 '11 at 1:24 I think the reasons for not returning memory to the kernel are overrated. If you do it right, you can avoid almost all of the cost - the main tricks are only returning unused ranges larger than a moderately-large threshold, and on consolidation of adjacent free blocks, only returning the new block when floor(log(size)) has increased.

I have an implementation working this way very successfully, and several questions on SO that were related to its development. – R.. May 15 '11 at 4:02 Also note that almost all malloc implementations use mmap directly for very large allocations, and thus can and do return them to the kernel when they're freed. – R.. May 15 '11 at 4:02 Note that the expression new_size^old_size>old_size is true if and only if new_size uses more bits than old_size.

You can change the right-hand side to old_size/2 or /4 for more fine-grained freeing with low impact on performance, if desired. – R.. May 15 '11 at 4:12.

Whenever free actually releases the memory is implementation dependent. So maybe free is not returning the memory right away when it's a big chunk on memory. I don't think it has anything to do with structs.

Mainly for performance reasons, the allocated heap memory won't be returned to the OS after being freed. It will be marked as free though, and maybe later the kernel will get it back, or your program will allocate it and use it again. I don't know what you used to alloc/free your (char *).

The difference you've seen might be that your (char *) was allocated on the stack, and the release/free process it different than with the heap (stack memory management is a lot simpler).

It is up to the OS to really free your data and thus shrink the memory consumption of your program. You only tell it, that you won't use that memory anymore.

I cant really gove you an answer,but what I can give you is a way to a solution, that is you have to find the anglde that you relate to or peaks your interest. A good paper is one that people get drawn into because it reaches them ln some way.As for me WW11 to me, I think of the holocaust and the effect it had on the survivors, their families and those who stood by and did nothing until it was too late.

Related Questions