Is there any danger in calling free() or delete in

2019-01-12 06:33发布

Possible Duplicate:
( POD )freeing memory : is delete[] equal to delete ?

Does delete deallocate the elements beyond the first in an array?

char *s = new char[n];
delete s;

Does it matter in the above case seeing as all the elements of s are allocated contiguously, and it shouldn't be possible to delete only a portion of the array?

For more complex types, would delete call the destructor of objects beyond the first one?

Object *p = new Object[n];
delete p;

How can delete[] deduce the number of Objects beyond the first, wouldn't this mean it must know the size of the allocated memory region? What if the memory region was allocated with some overhang for performance reasons? For example one could assume that not all allocators would provide a granularity of a single byte. Then any particular allocation could exceed the required size for each element by a whole element or more.

For primitive types, such as char, int, is there any difference between:

int *p = new int[n];
delete p;
delete[] p;
free p;

Except for the routes taken by the respective calls through the delete->free deallocation machinery?

10条回答
祖国的老花朵
2楼-- · 2019-01-12 07:01

Yes, this is dangerous!

Dont do it!

It will lead to programm crashes or even worse behavior!

For objects allocated with new you MUST use delete;

For objects allocated with new [] you MUST use delete [];

For objects allocated with malloc() or calloc() you MUST use free();

Be aware also that for all these cases its illegal to delete/free a already deleted/freed pointer a second time. free may also NOT be called with null. calling delete/delete[] with NULL is legal.

查看更多
放荡不羁爱自由
3楼-- · 2019-01-12 07:01

Raymond Chen (Microsoft developer) has an in-depth article covering scaler vs. vector deletes, and gives some background to the differences. See:

http://blogs.msdn.com/oldnewthing/archive/2004/02/03/66660.aspx

查看更多
狗以群分
4楼-- · 2019-01-12 07:03

Yes, there's a real practical danger. Even implementation details aside, remember that operator new/operator delete and operator new[]/operator delete[] functions can be replaced completely independently. For this reason, it is wise to think of new/delete, new[]/delete[], malloc/free etc. as different, completely independent methods of memory allocaton, which have absolutely nothing in common.

查看更多
smile是对你的礼貌
5楼-- · 2019-01-12 07:05

Although it might seem in some logic way that you can mix new[] and free or delete instead of delete[], this is under the assumption about the compiler being a fairly simplistic, i.e., that it will always use malloc() to implement the memory allocation for new[].

The problem is that if your compiler has a smart enough optimizer it might see that there is no "delete[]" corresponding to the new[] for the object you created. It might therefore assume that it can fetch the memory for it from anywhere, including the stack in order to save the cost of calling the real malloc() for the new[]. Then when you try to call free() or the wrong kind of delete on it, it is likely to malfunction hard.

查看更多
祖国的老花朵
6楼-- · 2019-01-12 07:10

Step 1 read this: what-is-the-difference-between-new-delete-and-malloc-free

You are only looking at what you see on the developer side.
What you are not considering is how the std lib does memory management.

The first difference is that new and malloc allocate memroy from two different areas in memory (New from FreeStore and malloc from Heap (Don't focus on the names they are both basically heaps, those are just there official names from the standard)). If you allocate from one and de-allocate to the other you will messs up the data structures used to manage the memory (there is no gurantee they will use the same structure for memory management).

When you allocate a block like this:

int*   x= new int; // 0x32

Memory May look like this: It probably wont since I made this up without thinking that hard.

Memory   Value      Comment
0x08     0x40       // Chunk Size  
0x16     0x10000008 // Free list for Chunk size 40
0x24     0x08       // Block Size
0x32     ??         // Address returned by New.
0x40     0x08       // Pointer back to head block.
0x48     0x0x32     // Link to next item in a chain of somthing.

The point is that there is a lot more information in the allocated block than just the int you allocated to handle memory management.

The standard does not specify how this is done becuase (in C/C++ style) they did not want to inpinge on the compiler/library manufacturers ability to implement the most effecient memory management method for there architecture.

Taking this into account you want the manufacturer the ability to distinguish array allocation/deallocation from normal allocation/deallocation so that it is possable to make it as effecient as possable for both types independantly. As a result you can not mix and match as internally they may use different data structures.

If you actually analyse the memory allocation differences between C and C++ applications you find that they are very different. And thus it is not unresonable to use completely different techniques of memory management to optimise for the application type. This is another reason to prefer new over malloc() in C++ as it will probably be more effecient (The more important reason though will always be to reducing complexity (IMO)).

查看更多
Rolldiameter
7楼-- · 2019-01-12 07:18

It's undefined behavior. Hence, the anser is: yes, there could be danger. And it's impossible to predict exactly what will trigger problems. Even if it works one time, will it work again? Does it depend on the type? Element count?

查看更多
登录 后发表回答