Difference between malloc and calloc?

后端 未结 14 1522
感情败类
感情败类 2020-11-22 03:40

What is the difference between doing:

ptr = (char **) malloc (MAXELEMS * sizeof(char *));

or:

ptr = (char **) calloc (MAXEL         


        
相关标签:
14条回答
  • 2020-11-22 03:56

    calloc is generally malloc+memset to 0

    It is generally slightly better to use malloc+memset explicitly, especially when you are doing something like:

    ptr=malloc(sizeof(Item));
    memset(ptr, 0, sizeof(Item));
    

    That is better because sizeof(Item) is know to the compiler at compile time and the compiler will in most cases replace it with the best possible instructions to zero memory. On the other hand if memset is happening in calloc, the parameter size of the allocation is not compiled in in the calloc code and real memset is often called, which would typically contain code to do byte-by-byte fill up until long boundary, than cycle to fill up memory in sizeof(long) chunks and finally byte-by-byte fill up of the remaining space. Even if the allocator is smart enough to call some aligned_memset it will still be a generic loop.

    One notable exception would be when you are doing malloc/calloc of a very large chunk of memory (some power_of_two kilobytes) in which case allocation may be done directly from kernel. As OS kernels will typically zero out all memory they give away for security reasons, smart enough calloc might just return it withoud additional zeroing. Again - if you are just allocating something you know is small, you may be better off with malloc+memset performance-wise.

    0 讨论(0)
  • 2020-11-22 03:56

    Number of blocks:
    malloc() assigns single block of requested memory,
    calloc() assigns multiple blocks of the requested memory

    Initialization:
    malloc() - doesn't clear and initialize the allocated memory.
    calloc() - initializes the allocated memory by zero.

    Speed:
    malloc() is fast.
    calloc() is slower than malloc().

    Arguments & Syntax:
    malloc() takes 1 argument:

    1. bytes

      • The number of bytes to be allocated

    calloc() takes 2 arguments:

    1. length

      • the number of blocks of memory to be allocated
    2. bytes

      • the number of bytes to be allocated at each block of memory
    void *malloc(size_t bytes);         
    void *calloc(size_t length, size_t bytes);      
    

    Manner of memory Allocation:
    The malloc function assigns memory of the desired 'size' from the available heap.
    The calloc function assigns memory that is the size of what’s equal to ‘num *size’.

    Meaning on name:
    The name malloc means "memory allocation".
    The name calloc means "contiguous allocation".

    0 讨论(0)
  • 2020-11-22 03:59

    There's no difference in the size of the memory block allocated. calloc just fills the memory block with physical all-zero-bits pattern. In practice it is often assumed that the objects located in the memory block allocated with calloc have initilial value as if they were initialized with literal 0, i.e. integers should have value of 0, floating-point variables - value of 0.0, pointers - the appropriate null-pointer value, and so on.

    From the pedantic point of view though, calloc (as well as memset(..., 0, ...)) is only guaranteed to properly initialize (with zeroes) objects of type unsigned char. Everything else is not guaranteed to be properly initialized and may contain so called trap representation, which causes undefined behavior. In other words, for any type other than unsigned char the aforementioned all-zero-bits patterm might represent an illegal value, trap representation.

    Later, in one of the Technical Corrigenda to C99 standard, the behavior was defined for all integer types (which makes sense). I.e. formally, in the current C language you can initialize only integer types with calloc (and memset(..., 0, ...)). Using it to initialize anything else in general case leads to undefined behavior, from the point of view of C language.

    In practice, calloc works, as we all know :), but whether you'd want to use it (considering the above) is up to you. I personally prefer to avoid it completely, use malloc instead and perform my own initialization.

    Finally, another important detail is that calloc is required to calculate the final block size internally, by multiplying element size by number of elements. While doing that, calloc must watch for possible arithmetic overflow. It will result in unsuccessful allocation (null pointer) if the requested block size cannot be correctly calculated. Meanwhile, your malloc version makes no attempt to watch for overflow. It will allocate some "unpredictable" amount of memory in case overflow happens.

    0 讨论(0)
  • 2020-11-22 03:59

    from an article Benchmarking fun with calloc() and zero pages on Georg Hager's Blog

    When allocating memory using calloc(), the amount of memory requested is not allocated right away. Instead, all pages that belong to the memory block are connected to a single page containing all zeroes by some MMU magic (links below). If such pages are only read (which was true for arrays b, c and d in the original version of the benchmark), the data is provided from the single zero page, which – of course – fits into cache. So much for memory-bound loop kernels. If a page gets written to (no matter how), a fault occurs, the “real” page is mapped and the zero page is copied to memory. This is called copy-on-write, a well-known optimization approach (that I even have taught multiple times in my C++ lectures). After that, the zero-read trick does not work any more for that page and this is why performance was so much lower after inserting the – supposedly redundant – init loop.

    0 讨论(0)
  • 2020-11-22 04:02

    calloc() gives you a zero-initialized buffer, while malloc() leaves the memory uninitialized.

    For large allocations, most calloc implementations under mainstream OSes will get known-zeroed pages from the OS (e.g. via POSIX mmap(MAP_ANONYMOUS) or Windows VirtualAlloc) so it doesn't need to write them in user-space. This is how normal malloc gets more pages from the OS as well; calloc just takes advantage of the OS's guarantee.

    This means calloc memory can still be "clean" and lazily-allocated, and copy-on-write mapped to a system-wide shared physical page of zeros. (Assuming a system with virtual memory.)

    Some compilers even can optimize malloc + memset(0) into calloc for you, but you should use calloc explicitly if you want the memory to read as 0.

    If you aren't going to ever read memory before writing it, use malloc so it can (potentially) give you dirty memory from its internal free list instead of getting new pages from the OS. (Or instead of zeroing a block of memory on the free list for a small allocation).


    Embedded implementations of calloc may leave it up to calloc itself to zero memory if there's no OS, or it's not a fancy multi-user OS that zeros pages to stop information leaks between processes.

    On embedded Linux, malloc could mmap(MAP_UNINITIALIZED|MAP_ANONYMOUS), which is only enabled for some embedded kernels because it's insecure on a multi-user system.

    0 讨论(0)
  • 2020-11-22 04:02

    A less known difference is that in operating systems with optimistic memory allocation, like Linux, the pointer returned by malloc isn't backed by real memory until the program actually touches it.

    calloc does indeed touch the memory (it writes zeroes on it) and thus you'll be sure the OS is backing the allocation with actual RAM (or swap). This is also why it is slower than malloc (not only does it have to zero it, the OS must also find a suitable memory area by possibly swapping out other processes)

    See for instance this SO question for further discussion about the behavior of malloc

    0 讨论(0)
提交回复
热议问题