I know how they are different syntactically, and that C++ uses new, and C uses malloc. But how do they work, in a high-level explanation?
views:
1103answers:
5"new" does a lot more than malloc. malloc simply allocates the memory - it doesn't even zero it for you. new initialises objects, calls contructors etc. I would suspect that in most implementations new is little more than a thin wrapper around malloc for basic types.
In C: malloc allocates a chunk of memory of a size that you provide in an argument, and returns back a pointer to this memory.
The memory is declared on the heap, so make sure to deallocate it when you are finished.
What new
does differently form malloc
is the following:
- It constructs a value in the allocated memory, by calling
operator new
. This behaviour can be adapted by overloading this operator, either for all types, or just for your class. - It calls handler functions if no memory can be allocated. This gives you the opportunity to free the required memory on the fly if you have registered such a handler function beforehand.
- If that doesn't help (e.g. because you didn't register any function), it throws an exception.
So all in all, new
is highly customizable and also does initialization work besides memory allocation. These are the two big differences.
Although malloc
/free
and new
/delete
have different behaviors, they both do the same thing at a low level: manage dynamically allocated memory. I'm assuming this is what you're really asking about. On my system, new
actually calls malloc
internally to perform its allocation, so I'll just talk about malloc
.
The actual implementation of malloc
and free
can vary a lot, since there are many ways to implement memory allocation. Some approaches get better performance, some waste less memory, others are better for debugging. Garbage collected languages may also have completely different ways of doing allocation, but your question was about C/C++.
In general, blocks are allocated from the heap, a large area of memory in your program's address space. The library manages the heap for you, usually using system calls like sbrk
or mmap
. One approach to allocating blocks from the heap is to maintain a list of free and allocated blocks which stores block sizes and locations. Initially, the list might contain one big block for the whole heap. When a new block is requested, the allocator will select a free block from the list. If the block is too large, it can be split into two blocks (one of the requested size, the other of whatever size is left). When an allocated block is freed, it can be merged with adjacent free blocks, since having one big free block is more useful than several small free blocks. The actual list of blocks can be stored as separate data structures or embedded into the heap.
There are many variations. You might want to keep separate lists of free and allocated blocks. You might get better performance if you have separate areas of the heap for blocks of common sizes or separate lists for those sizes. For instance, when you allocated a 16-byte block, the allocator might have a special list of 16-byte blocks so allocation can be O(1). It may also be advantageous to only deal with block sizes that are powers of 2 (anything else gets rounded up). For instance, the Buddy allocator works this way.