Malloc allocating same block of memory - c

I used C library malloc to allocate 8MB memory, after using that memory I used free to free the 8MB memory.
But when i used malloc again to allocate 8MB of memory, it is allocating the same location as allocated previously.
How to avoid this problem and why does this occur?
EDIT: I'm implementing a tool to test main memory, if malloc allocates the same block of memory it is not possible to check the whole memory

This is not a problem per se, and is by design. Typical implementations of malloc will recycle blocks of memory for reasons of performance. In any case, since malloc returns addresses from a limited pool of values, there's no way it could guarantee not to recycle blocks.
The only sure fire way to stop malloc returning blocks that is has returned before is to stop freeing them. Of course, that's not really very practical.
I'm implementing a tool to test main memory. If malloc allocates the same block of memory it is not possible to check the whole memory.
Your tool to test main memory cannot be implemented with malloc, or indeed by any user mode program. Modern operating systems don't give you access to physical memory. Rather they present a virtualized view of memory. The addresses in your program are not physical addresses, they are virtual address. Testing physical memory requires you to go in at a much lower level than is possible from a user mode program.

This should help you
How malloc works?
To prevent this, allocate a few bytes using malloc/calloc and then free the bigger chunk of memory.
BTW this is not a wrong behavior to get the same memory address.
You might want to call system() to run a few linux commands (that provide detailed memory mgmt options) from your code.Main memory management cannot be done/tested using malloc/free, they are limited to operating on the memory allocated to your program when it is running.

Related

How does memory allocation take place on using malloc in a loop >

How does memory allocation take place in this case?
I observed that this is not the same as using a malloc on 1000000*10000 directly, which should have lead to 4*10GB (4 bytes per int) being allocated. However, this piece of code uses only 200MB on executing.
for(int i=0;i<1000000;i++)
{
int *A = (int*)malloc(sizeof(int)*10000);
}
As mentioned, there are differences in whether the memory is allocated in chunks or as one. The main reason why you're not seeing the memory being allocated is due to the operating systems lying about memory.
If you allocate a block of memory the allocation is virtual. Since all processes have lots of virtual memory available, it will usually succeed (unless you ask for insane amounts of memory, or the OS otherwise determines it's not going to work). The actual reservation of physical memory may occur after you actually use the memory.
So when you look at memory usage, there is not only one number but several. There is shared memory, there is memory that can't be paged out, there's the virtual allocated memory and then there's the actual memory in use.
If you change the code to actually use the memory, for example just write one byte to the allocated section, you will see completely different result. The OS has to handle the memory allocation and get the memory blocks in physical memory.
Also as mentioned you don't check that malloc succeeds. Maybe it succeeds for a few times and then doesn't allocate anything more.
This system also explains why sometimes a process might get killed due to low memory even though all allocations succeeded in all processes. The OS was just being too optimistic and thought it could give out more memory than actually was possible.
The difference is how the memory is allocated.
When you call 10K times malloc to allocate 10k of memory, 10G of virtual memory is allocated to your process. The resulting 10G of memory is not continuous. That is, you get 10k scattered blocks of memory whose size is 10K. Whereas, when you call malloc requesting 10G, malloc will try to allocate a continuos block of memory whose size is 10G.
According to the malloc manual page, malloc fails when it can't allocate the requested memory. You should check if the malloc is successful in your application, in order to understand if the memory has been correctly allocated.
for(int i=0;i<1000000;i++)
{
int *A = (int*)malloc(sizeof(int)*10000);
}
This is a perfect way of memory leak. You are allocating 1000000 times, each time sizeof(int)*10000 bytes. You're guaranteed to leak all of these allocated memory. As you declared A within the loop, so after the loop you do not have handle to that variable any more, and there's no way to free even the last chunk of memory you allocated.
And of course this is different from allocating 1000000*10000*sizeof(int) in one go. The former allocates 1000000 smaller chunks which are mostly to be scattered in many memory location. The latter tries to allocate one gigantic chunk, which likely to fails.

C, Xcode and memory

Why after executing next C-code Xcode shows 20KB more than it was?
void *p = malloc(sizeof(int)*1000);
free(p);
Do I have to free the memory another way? Or it's just an Xcode mistake?
When you say "Xcode shows 20KB more than it was", I presume you mean that the little bar graph goes up by 20kB.
When you malloc an object, the C library first checks the process's address space to see if there is enough free space to satisfy the request. If there isn't enough memory, it goes to the operating system to ask for more virtual memory to be allocated to the process. The graph in Xcode measures the amount of virtual memory the process has.
When you free an object, the memory is never returned to the operating system, rather, it is "just" placed on the list of free blocks for malloc to reuse. I put the word "just" in scare quotes because the actual algorithm can be quite complex, in order to minimise fragmentation of the heap and the time taken to malloc and free blocks. The reason memory is never returned to the operating system is that it is very expensive to do system calls to the OS to get and free memory.
Thus, you will never see the memory usage of the process go down. If you malloc a Gigabyte of memory and then free it, the process will still appear to be using a Gigabyte of virtual memory.
If you want to see if your program really leaks, you need to use the leaks profile tool. This intercepts malloc and free calls so it knows which blocks are still nominally in use and which have been freed.

free() not freeing memory in embedded linux.

I have allocated memory using malloc() in embedded Linux (around 10 MB). And checked the free memory it was 67080 kB but even after freeing it using free() it remains the same. It is only after the application is terminated the memory is available again. Does free() not make the freed memory available to the system, if so how to make it available.
free is a libc library call. it marks heap space as available for reuse. It does not guarantee that the associated virtual mapping will be released. Only after a dirty virtual mapping is released by your OS, then that memory will be system wide free again. This can only happen in chunks of pages.
Also if you allocated memory using malloc and family and didn't use it then it didn't actually consume physical memory until then - so freeing it will do nothing.
Does free() not make the freed memory available to the system.
No, usually not.
malloc() normally requests memory from the OS by the low level sbrk() or mmap() call. Once assigned to the application, free() just returns the memory to a memory pool that belongs to the application. That is, it's not returned back to the OS for use in another process. (Though some heuristics are in-place to do so in certain circumstances).
If swap space is in place, this becomes less of a problem, the OS will swap out the unused memory of applications to make room for additional physical memory that's required.
if so how to make it available.
Exit the application.
Or you would need to write your own memory allocator that could do this.(which in the general case is not an easy task especially if you don't want to sacrifice overhead and speed).
For a relatively big single piece of 10MB, you could simply request anonymous memory with mmap() and the memory will be released back to the OS when you munmap() that piece of memory.
Taken from the malloc 3 man page:
Normally, malloc() allocates memory from the heap, and adjusts the
size of the heap as required, using sbrk(2). When allocating blocks
of memory larger than MMAP_THRESHOLD bytes, the glibc malloc()
implementation allocates the memory as a private anonymous mapping
using mmap(2). MMAP_THRESHOLD is 128 kB by default, but is
adjustable using mallopt(3)
You can try to modify the MMAP_THRESHOLD so that by using malloc you are invoking mmap. If you do so, free guarantees that the memory allocated through mmap will return back to the system as soon as you free it.
Your malloc() calls obtain memory from the system, and maintain a heap data structure for keeping track of used and free memory within the process. Your free() calls return memory to the heap, where they are marked free, but they're still part of the process's memory.
If you want memory deallocation to return pages to the system, you'll have to write your own memory manager, but keep in mind that it'll only be able to completely free memory under the right conditions: It depends on the behavior of your application, whether your allocations and deallocations span page boundaries and cleanly de-fragment, etc. You need to understand the memory allocation behavior of your application to know whether this will be any benefit.

Is calloc exactly the same as malloc + memset?

In linux, is calloc exactly the same as malloc + memset or does this depend on the exact linux/kernel version?
I am particularly interested in the question of whether you can calloc more RAM than you physically have (as you can certainly malloc more RAM than you physically have, you just can't write to it). In other words, does calloc always actually write to the memory you have been allocated as the specs suggest it should.
Of course, that depends on the implementation, but on a modern day Linux, you probably can. Easiest way is to try it, but I'm saying this based on the following logic.
You can malloc more than the memory you have (physical + virtual) because the kernel delays allocation of your memory until you actually use it. I believe that's to increase the chances of your program not failing due to memory limits, but that's not the question.
calloc is the same as malloc but zero initializes the memory. When you ask Linux for a page of memory, Linux already zero-initializes it. So if calloc can tell that the memory it asked for was just requested from the kernel, it doesn't actually have to zero initialize it! Since it doesn't, there is no access to that memory and therefore it should be able to request more memory than there actually is.
As mentioned in the comments this answer provides a very good explanation.
Whether calloc needs to write to the memory depends on whether it got the allocation from heap pages that are already assigned to the process, or it had to request more memory be assigned to the process by the kernel (using a system call such as sbrk() or mmap()). When the kernel assigns new memory to a process, it always zeroes it first (typically using a VM optimization, so it doesn't actually have to write to the page). But if it's reusing memory that was assigned previously, it has to use memset() to zero it.
It is not mentioned in the cited duplicate or here. Linux uses virtual memory and can allocate more memory that physically available in the system. A naive implementation of calloc() that simply does a malloc() plus memset() in user space will touch every page.
As Linux typically allocates in 4k chunks, all of the calloc() blocks are the same and initially read as zero. That is the same 4k chunk of memory can be mapped read only and the entire calloc() space in only taking up approximately size/4k * pointer_size + 4k. As the program writes to the calloc() space, a page fault happens and Linux will allocate a new page (4k) and resume the program.
This is called copy-on-write or COW for short. malloc() will generally behave the same way. For small sizes, the 'C' library will use binning and share 4k pages with other small sized allocation.
So, there are typically two layers involved.
Linux kernel's process memory management.
glibc heap management.
If the memory size requested is large and requires new memory allocated to the process, then most of the above applies (via Linux's process memory management). However, if the memory requested is small, then it will be like a malloc() plus memset(). In the large allocation size, the memset() is damaging as it touches the memory and the kernel thinks it needs a new page to allocate.
You can't malloc(3) more ram than the kernel gives the process doing the malloc(3)-ing. malloc(3) returns NULL if you can't allocate the amount of memory you want to allocate. In addition, malloc(3) and memset(3) are defined by your c library (libc.so) and not your kernel. The Linux kernel defines mmap(2) and other low-level memory allocation functions, not the *alloc(3) family (excluding kalloc()).

Limit Virtual Memory space for malloc()

I have written my own my_malloc() function that manages its own physical memory. In my application I want to be able use both the libc malloc() as well as my own my_malloc() function. So I somehow need to partition the virtual address space, malloc should always assign a virtual address only if its from its dedicated pool, same thing with my_malloc(). I cannot limit heap size, I just need to guarantee that malloc() and my_malloc() never return the same/overlapping virtual addresses.
thanks!
One possibility would be to have my_malloc() call malloc() at startup to pre-allocate a large pool of memory, then apportion that memory to its callers and manage it accordingly. However, a full implementation would need to handle garbage collection and defragmentation.
Another possibility would be to have my_malloc() call malloc() each time it needs to allocate memory and simply handle whatever "bookkeeping" aspects you're interested in, such as number of blocks allocated, number of blocks freed, largest outstanding block, total allocated memory, etc. This is by far the safer and more efficient mechanism, as you're passing all of the "hard" operations to malloc().
One answer is to make your my_malloc use memory allocated by malloc. Using big enough blocks would mostly acheive that; then within each block your version will maintain its own structures and allocate parts of it to callers.
It gets tricky because you can't rely on extending the entire available space for your version, as you can when you get memory from sbrk or similar. So your version would have to maintain several blocks.
Reserve a large block of virtual address space, and have that be the pool from which my_malloc() allocates. Once you have reserved a large contiguous region of memory from the OS, then subsequent calls to malloc() have to come from elsewhere.
For example, on Windows, you can use VirtualAlloc() to reserve a 256mb block of space. The memory won't actually be allocated until you "commit" it with a subsequent call, but it will reserve an address range (such as 0x4000000-0x5000000) which subsequent malloc() will not use. Then your my_malloc() can commit blocks out of this reserved range as requested, and subdivide them by whatever allocation scheme you've written.
I'm told the equivalent Linux call is mmap(). (edit: I previously said "kmalloc or vmalloc, depending on whether you need the memory to be physically contiguous or not," but those are kernel-level functions.)
We use this mechanism in our app to redirect all allocations of a certain size into our own custom pooled-block allocator for speed and efficiency. Among other things, it lets us reserve virtual pages in certain specific sizes that are more efficient for the CPU to handle.
If you add an mmap(2) call near the start of the program, you can allocate as much memory as you need with whatever addresses you need (see the hint, that's usually left NULL for the OS to determine) immediately; that will prevent malloc(3), or any other memory allocation routines, from getting those particular pages.
Don't worry about the memory usage; since modern systems are quite happy to overcommit, you'll only use a few hundred kilobytes more kernel space to handle page tables. Not too bad.

Resources