简体   繁体   中英

C: malloc(), free() and then again malloc() does work same always?

I have tried to run this code in some different machines with different processor and main memory size.

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    // your code goes here

    int *a, i;

    a = (int *)malloc(10*(sizeof(int)));

    for(i = 0; i < 10; i++)
    {
        a[i] = i*i;
    }

    free(a); 

    a = (int *)malloc(10*(sizeof(int)));

    for(i = 0; i < 10; i++)
    {
        printf("%d\n",a[i]);
    }

    free(a);

    return 0;
}

However, in all machines it generates the same output:

0
1
4
9
16
25
36
49
64
81

My question is: should the variable 'a' always allocate use the same memory location for the execution?

In theory, probably it is not mandatory. If my understanding is right: every malloc of 'a' can allocate a different base address.

However, what does actually happen in practice by modern computing machines?

Modern memory allocators have several performance optimizations. They have several buckets of available memory and each time you request an amount of bytes they look and determine the best memory region available. Some memory allocators keep a pointer to the last allocation you made so if you need another piece of the same size (something that happens often), they give you the same piece back so they don't have to look for a new one, which takes time.

You can try two calls to malloc() and then to free() and then to malloc() again to see what happens.

There are no guarantees this will work. (And, in fact, it doesn't work with a debug build in Visual Studio because the debug memory allocator will clobber the data when you free it in order to detect bugs like this.)

You should never depend on this behavior.

Some memory managers use LIFO (last-in, first-out) lists of freed blocks of memory. This means that the next allocation of the same size is likely to get the same block back. Other memory managers explicitly don't use LIFO free-lists to make it harder for malware to exploit a heap management bug.

It happens in practice because re-using a just-freed chunk of memory is usually the best choice. It's probably still hot in cache, and it means malloc's free-list can be shortened (instead of leaving that block on the free list and getting a new block from the OS).

It also means malloc probably doesn't need any system calls to satisfy this request. Small free() calls are typically not returned to the OS right away (because usually they can't be, because they're just part of a page). So typical malloc implementations put them on a free-list.

So this little experiment has told you something about the internal implementation of malloc on the particular C implementation you tried it on. As I think you realize from the question phrasing, this is undefined behaviour and should never be relied upon .

It's not really specific to CPU architecture. AFAIK, GNU libc's malloc uses the same algorithms on every architecture.


Even on a C implementation that does work this way, there are many ways for this to break: a signal handler could run between the free and the second malloc, and take the block. In multithreaded code, another thread could take that block between the free and the malloc. (Although this is less likely: each thread would usually use its own small pool).


A large buffer usually would be handed back to the OS inside the free() call, so the next malloc() would have to get fresh memory from the OS again. See M_MMAP_THRESHOLD in mallopt(3) for an explanation of that tunable parameter in glibc's malloc. M_PERTURB provides similar functionality to what Adrian describes for MSVC++ debug builds: breaking code that has use-after-free bugs, and breaking code that depends on malloc ed memory being zeroed or something (use calloc to efficiently get zeroed memory).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM