malloc question

Hi,

This code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
#include <stdio.h>
#include <stdlib.h>
char* xxx(){
	char* yyy = malloc(sizeof(char)*1024);
	return yyy;
}
int main(int argc, char *argv[]){
	char *x;
	int i;
	system("clear");
	system("free -m");
	for(i=0; i < 1024*1024; i++){
		x = xxx();
		free(x);
	}
	system("free -m");
	return 0;
}


Gives me this output:
1
2
3
4
5
6
7
8
             total       used       free     shared    buffers     cached
Mem:          2027        817       1210          0         38        369
-/+ buffers/cache:        409       1617
Swap:         2588          0       2588
             total       used       free     shared    buffers     cached
Mem:          2027        818       1209          0         38        369
-/+ buffers/cache:        410       1616
Swap:         2588          0       2588


Why the diference of memory usage before and after?

Thanks
It says there's one more MiB used by buffers and cache. That's not necessarily related to the code. It certainly doesn't indicate memory leaks.

This isn't so much a question about malloc() as it is a question about UNIX and how it optimizes access times.
Last edited on
The system doen't necessarily release the memory at the moment you ask it to. free() just tells the system that it can release the memory. What does free say after the program exits?

BTW, sizeof(char) is always 1, so it's not a useful expression.
AFAIK, free() is instantaneous. Allocated memory cannot be used for something else until it is freed, so it doesn't make sense to delay deallocation. Allocation, on the other hand, may be delayed.
BTW, sizeof(char) is always 1, so it's not a useful expression.


Yeah, but I think it is still a good idea to do it so people can see more easily what is going on.
AFAIK, free() is instantaneous

That makes more sense. So what must be happening is that malloc has a MiB set aside for an allocation table to manage the memory and hasn't deallocated the table. Although that doesn't make much sense either since the program is only allocating a KiB at a time and deallocating it before allocating the next KiB, which hardly merits a MiB table. I'd like to see the result after allocating/deallocating a KiB only once.
Like this?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
#include <stdio.h>
#include <stdlib.h>
char* xxx(){
	char* yyy = malloc(sizeof(char)*1024);
	return yyy;
}
int main(int argc, char *argv[]){
	char *x;
	//system("clear");
	system("free -m");
	x = xxx();
	free(x);
	system("free -m");
	return 0;
}


Now there is no change...
1
2
3
4
5
6
7
8
             total       used       free     shared    buffers     cached
Mem:          2027        507       1519          0         16        248
-/+ buffers/cache:        243       1783
Swap:         2588          0       2588
             total       used       free     shared    buffers     cached
Mem:          2027        507       1519          0         16        248
-/+ buffers/cache:        243       1783
Swap:         2588          0       2588
In bytes:
1
2
3
4
5
6
7
8
             total       used       free     shared    buffers     cached
Mem:    2125963264  616640512 1509322752          0   71327744  271323136
-/+ buffers/cache:  273989632 1851973632
Swap:   2714300416          0 2714300416
             total       used       free     shared    buffers     cached
Mem:    2125963264  616640512 1509322752          0   71327744  271323136
-/+ buffers/cache:  273989632 1851973632
Swap:   2714300416          0 2714300416

Last edited on
Every malloc() does not result in a call to the operating system to allocate memory. See man 2 sbrk.

When the C++ memory manager runs out of heap space to allocate, it calls sbrk() to the kernel to request more memory. But it requests a *lot* more; not just the 12 bytes or whatever you requested, because the kernel can only give out memory to applications in units of a page at a time.

Furthermore, in some OSes (such as Linux configured with an optimistic allocation strategy), all sbrk() does is to extend the virtual address space of the application process. It does not actually allocate the physical pages behind that memory. Rather, the physical page is actually given to the process on the first access. This is why it is called an optimistic strategy--the kernel just assumes the memory will be there when you need it. This is also what makes handling out-of-memory conditions virtually impossible:

1
2
3
4
5
// This line might very well succeed (ie, not throw std::bad_alloc):
char* big_array = new char[ 10 * 1024 * 1024 ];  // 10M

// But this line might crash because of out of memory condition:
big_array[ 0 ] = 0;


The long and short of it is that you need to understand precisely how C++'s heap manager works and how your operating system handles memory allocations in order to even stand a chance at rationalizing what is going on. Furthermore, at least on some OSes (again, my experience is with Linux), the amount of free memory reported by the OS is totally useless. You can write a program that attempts to malloc pages at a time until the free memory reaches zero, but you'll find that the program gets killed by the OOM killer long before the free page count hits zero.
I see ... thanks for this clear and straight to the point answer.
Nevertheless it is a good practice to always use free(x) after a malloc right?
It is good practice to release dynamically allocated memory after you are done with it.
Topic archived. No new replies allowed.