开发者

Difference in implementation of malloc and new. Stack implementation?

While allocating memory, the new operator throws an exception if the memory is not available. On the other hand, malloc returns a NULL. What is the reason for the difference in implementation. Also, on static memory allocation, i.e. on the stack, is there an exception if we run out of memory?

I have already gone through the link 开发者_StackOverflow社区What is the difference between new/delete and malloc/free? but did not get my answer on the difference in implementation of the two


The problem with C code is that you are supposed to check the return value of function to make sure they worked correctly. But a lot of code was written that did not check the return value and as a result blew up very nicely when you least expected it.

In the worst case scenario it does not even crash immediately but continues on corrupting memory crashing at some point miles down stream of the error.

Thus in C++ exceptions were born.
Now when there is an error the code does not continue (thus no memory corruption) but unwinds the stack (potentially forcing the application to quit). If you can handle the problem you have to explicitly add code to handle the situation before continuing. Thus you can not accidentally forget to not check the error condition; you either check it or the application will quit.

The use of new fits this design.
If you fail to allocate memory then you must explicitly handle the error.
There is no opportunity to forget to check for the NULL pointer. Thus you can't go and mess up memory by accidentally using a NULL pointer.

Also, on static memory allocation, i.e. on the stack, is there an exception if we run out of memory?

Unfortunately you can not rely on this.
It is implementation defined what happens on stack-overflow. On a lot of systems it is not even possible to detect the situation resulting in memory corruption and probably ultimately a crash.

Note

If you #include <new> then there is a no throw version of new that you can use that returns NULL when there is no memory left. It is best avoided unless have some specialized need.


malloc cannot throw an exception, because that would break compatibility with C. new throws an exception because that is the preferred way in C++ to signal errors.

As far as I know, in early versions of C++, new did indeed return 0 on failure,


One important difference, I suppose, lies in the fact that :

  • malloc is the C-way of allocating memories ; and there were no exceptions in C
  • new is the C++, object-oriented and all, way ; and there are exceptions in C++, and using them is more clean.


Why keep malloc in C++ ? I suppose it's because C++ compiler can also work with C code...

... But I've often heard (from teachers, while I was still at school, a couple of years ago) that using malloc in C++ is discouraged, and new should be used instead.


At the risk of perhaps adding some confusion...

  • malloc is a regular C-function. Because it is C, it can only signal errors by ways that fit into a C program: using the return value, an argument passed by pointer or a global variable (like errno).
  • new introduces a C++ expression, it calls the operator new to obtain memory and then constructs the object. Either the operator new or the constructors may throw.

Note: there is a no throw version of the new expression

Most operator new are generally implemented in term of malloc, but as I noted there is more to a new expression than simply getting memory, since it's also builds the object(s).

It also takes care of managing up until it releases it to you. That is, if the constructor throws, then it properly disposes of the memory that was allocated, and in case of the new[] expression (which builds an array), calls the destructor of those objects that were already built.

Regarding stack overflows: it depends on your compiler and your operating system. The OS might remark the issue and signals the error, the compiler might check etc...

Note that gcc introduces the split-stack option to compiling, which consists in allocating a minimal stack and then growing it on demand. This neatly sidesteps the issue of possible stack-overflows, but introduces yet another binary compatibility issue since interaction with code that was not built with this option could get hazy; I don't know how they plan on implementing this exactly.


For the sake of completeness, remember also, that you can simulate the old (non throwing) method using nothrow -- this is especially suitable for performance critical parts of your code:

// never throws
char* ptr = new (nothrow) char [1024*1024];

// check pointer for succeeded allocation
if ( !ptr ) { 
  ... // handle error
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜