[ACCEPTED]-How do 'malloc' and 'new' work? How are they different (implementation wise)?-c
I'm just going to direct you to this answer: What is the difference between new/delete and malloc/free? . Martin 23 provided an excellent overview. Quick overview 22 on how they work (without diving into how you 21 could overload them as member functions):
new-expression and allocation
- The code contains a new-expression supplying the type-id.
- The compiler will look into whether the type overloads the operator new with an allocation function.
- If it finds an overload of an operator new allocation function, that one is called using the arguments given to new and sizeof(TypeId) as its first argument:
Sample:
new (a, b, c) TypeId;
// the function called by the compiler has to have the following signature:
operator new(std::size_t size, TypeOfA a, TypeOfB b, TypeOf C c);
- if operator new fails to allocate storage, it can call
new_handler
, and hope it makes place. If there still is not enough place, new has to throwstd::bad_alloc
or derived from it. An allocator that hasthrow()
(no-throw guarantee), it shall return a null-pointer in that case. - The C++ runtime environment will create an object of the type given by the type-id in the memory returned by the allocation function.
There 20 are a few special allocation functions given 19 special names:
no-throw
new. That takes anothrow_t
as second argument. A new-expression of the form like the following will call an allocation function taking only std::size_t and nothrow_t:
Example:
new (std::nothrow) TypeId;
placement new
. That takes a void* pointer as first argument, and instead of returning a newly allocated memory address, it returns that argument. It is used to create an object at a given address. Standard containers use that to preallocate space, but only create objects when needed, later.
Code:
// the following function is defined implicitly in the standard library
void * operator(std::size_t size, void * ptr) throw() {
return ptr;
}
If the allocation 18 function returns storage, and the the constructor 17 of the object created by the runtime throws, then 16 the operator delete is called automatically. In 15 case a form of new was used that takes additional 14 parameters, like
new (a, b, c) TypeId;
Then the operator delete 13 that takes those parameters is called. That 12 operator delete version is only called if 11 the deletion is done because the constructor 10 of the object did throw. If you call delete 9 yourself, then the compiler will use the 8 normal operator delete function taking only 7 a void*
pointer:
int * a = new int;
=> void * operator new(std::size_t size) throw(std::bad_alloc);
delete a;
=> void operator delete(void * ptr) throw();
TypeWhosCtorThrows * a = new ("argument") TypeWhosCtorThrows;
=> void * operator new(std::size_t size, char const* arg1) throw(std::bad_alloc);
=> void operator delete(void * ptr, char const* arg1) throw();
TypeWhosCtorDoesntThrow * a = new ("argument") TypeWhosCtorDoesntThrow;
=> void * operator new(std::size_t size, char const* arg1) throw(std::bad_alloc);
delete a;
=> void operator delete(void * ptr) throw();
new-expression and arrays
If you do
new (possible_arguments) TypeId[N];
The compiler is using 6 the operator new[]
functions instead of plain operator new
. The operator 5 can be passed a first argument not exactly 4 sizeof(TypeId)*N
: The compiler could add some space to store 3 the number of objects created (necassary 2 to be able to call destructors). The Standard 1 puts it this way:
new T[5]
results in a call of operatornew[](sizeof(T)*5+x)
, andnew(2,f) T[5]
results in a call of operatornew[](sizeof(T)*5+y,2,f)
.
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 3 all in all, new
is highly customizable and 2 also does initialization work besides memory 1 allocation. These are the two big differences.
Although malloc
/free
and new
/delete
have different behaviors, they 44 both do the same thing at a low level: manage 43 dynamically allocated memory. I'm assuming 42 this is what you're really asking about. On 41 my system, new
actually calls malloc
internally to 40 perform its allocation, so I'll just talk 39 about malloc
.
The actual implementation of malloc
and 38 free
can vary a lot, since there are many ways 37 to implement memory allocation. Some approaches 36 get better performance, some waste less 35 memory, others are better for debugging. Garbage 34 collected languages may also have completely 33 different ways of doing allocation, but 32 your question was about C/C++.
In general, blocks 31 are allocated from the heap, a large area 30 of memory in your program's address space. The 29 library manages the heap for you, usually 28 using system calls like sbrk
or mmap
. One approach 27 to allocating blocks from the heap is to 26 maintain a list of free and allocated blocks 25 which stores block sizes and locations. Initially, the 24 list might contain one big block for the 23 whole heap. When a new block is requested, the 22 allocator will select a free block from 21 the list. If the block is too large, it 20 can be split into two blocks (one of the 19 requested size, the other of whatever size 18 is left). When an allocated block is freed, it 17 can be merged with adjacent free blocks, since 16 having one big free block is more useful 15 than several small free blocks. The actual 14 list of blocks can be stored as separate 13 data structures or embedded into the heap.
There 12 are many variations. You might want to keep 11 separate lists of free and allocated blocks. You 10 might get better performance if you have 9 separate areas of the heap for blocks of 8 common sizes or separate lists for those 7 sizes. For instance, when you allocated 6 a 16-byte block, the allocator might have 5 a special list of 16-byte blocks so allocation 4 can be O(1). It may also be advantageous 3 to only deal with block sizes that are powers 2 of 2 (anything else gets rounded up). For 1 instance, the Buddy allocator works this way.
"new" does a lot more than malloc. malloc 6 simply allocates the memory - it doesn't 5 even zero it for you. new initialises objects, calls 4 contructors etc. I would suspect that in 3 most implementations new is little more 2 than a thin wrapper around malloc for basic 1 types.
In C: malloc allocates a chunk of memory 4 of a size that you provide in an argument, and 3 returns back a pointer to this memory.
The 2 memory is declared on the heap, so make 1 sure to deallocate it when you are finished.
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.