views:

512

answers:

7
IP_ADAPTER_INFO *ptr=new IP_ADAPTER_INFO[100];

if i free using

delete ptr;

will it lead to memory leak, if not then why ?

This is disassembly code generated by VS2005

**delete ptr;**
0041351D  mov         eax,dword ptr [ptr] 
00413520  mov         dword ptr [ebp-0ECh],eax 
00413526  mov         ecx,dword ptr [ebp-0ECh] 
0041352C  push        ecx  
0041352D  call        operator delete (4111DBh) 
00413532  add         esp,4 
    **delete []ptr;**
00413535  mov         eax,dword ptr [ptr] 
00413538  mov         dword ptr [ebp-0E0h],eax 
0041353E  mov         ecx,dword ptr [ebp-0E0h] 
00413544  push        ecx  
00413545  call        operator delete[] (4111E5h) 
0041354A  add         esp,4
+6  A: 

This FAQ answers exactly this question.

Naveen
:) thanks for link
sat
My question was will it leak memory !
sat
It is undefined..
Naveen
Yes. if you use delete this will lead to memory leak. You should use delete[]. Check the links from my answer.
Andrejs Cainikovs
And the answer is a very definite _it might_. And then it might not. Or will it? You can debug through the generated machine code and look for yourself. And then you will know whether it did - in the very moment you debugged. Because it might change the next time you compile the app, or run it, or without a debugger present, or... And that's just an infinitely small subset of what _Undefined Behavior_ means.
sbi
@singh The answer= 'maybe' :-)
Chris Huang-Leaver
+1  A: 

If A points to an array that was allocated via new T[n], then you must delete it via delete[] A.

Why?

The difference between delete and delete[] is straightforward - the former destroys a scalar object and the latter destroys an array.

More info here and here.

UPDATE 1 (wrong):

If you use delete (and not delete[]) while allocating with new T[n], only first element is freed while others are not destructorized, which will lead to memory leak. Why? This is the way Bjarne Stroustrup and others had designed the language. And it is not compiler-varying. If one compiler deallocates the different way, it is just not following the standard. The C++ Programming Language, chapters 6.2.6.2 and 19.4.5.

UPDATE 2 (correct):

I'm admitting my mistake about behavior of using delete operator on allocations with new T[n]. Reading the mentioned document I didn't find the exact description so I suppose in this situation the behavior will be undefined and will vary on from compiler to compiler. AFAIK, MSVC compiler for example will produce different code than GCC. Please ignore UPDATE 1.

Andrejs Cainikovs
Nobody (not even Bjarne, let alone some Bjorn) specified that only one object would be freed. It's _undefined_. (And, as I said elsewhere, I have worked with at least one compiler which freed them all.)
sbi
I guess you mean Bjarne, not Bjorn?
gnud
Fixed. Sorry, Bjarne :-)
Andrejs Cainikovs
sbi, the behavior for particular compiler *may* be undefined. But, as I said, this compiler is not following the C++ standard. Check http://www.research.att.com/~bs/. There is few mentions for this specific question.
Andrejs Cainikovs
_this compiler_ - I don't see a reference to a specific compiler (anymore) ? "Undefined Behavior" is an ISO Standard term, and does not refer to any specific implementation.
MSalters
I'll repeat, this particular **behavior** is defined by a standard.
Andrejs Cainikovs
The C++ standard explicitly states (at least in it draft version from 13.9.2001 I have at hand) that such behavior is undefined:In the first alternative (delete object), the value of the operand of delete shall be a pointer to a non-array object or a pointer to a sub-object (1.8) representing a base class of such an object (clause 10). If not, the behavior is undefined. In the second alternative (delete array), the value of the operand of delete shall be the pointer value which resulted from a previous array new-expression.72) If not, the behavior is undefined.
Komat
@Andrejs: Chapter and verse, please.
sbi
The C++ Programming Language 6.2.6.2, 19.4.5
Andrejs Cainikovs
Neither of those exist in my copy (C++98). Anyway, the standard only specifies what you said before the updates: One destroys a scalar object, the other destroys an array. It does *not* say what you have in your first update, that if the scalar delete is invoked on an array, the first object is destroyed. That is **not** guaranteed by the standard. It is just undefined.
jalf
I would have upvoted but after reading "Update", i better not :(
Johannes Schaub - litb
Thanks jalf, sbi, Komat. You where right, I'd admitted my mistake and updated the post.
Andrejs Cainikovs
+25  A: 

Whether this leads to a memory leak, wipes your hard disk, gets you pregnant, makes nasty Nasal Demons chasing you around your apartment, or lets everything work fine with no apparent problems, is undefined. It might be this way with one compiler, and change with another, change with a new compiler version, with each new compilation, with the moon phases, your mood, or depending on the number or neutrinos that passed through the processor on the last sunny afternoon. Or it might not.

All that, and an infinite amount of other possibilities are put into one term: Undefined behavior:

Just stay away from it.

sbi
I would say that "Undefined behavior" is "bad" and should be avoided, as you say. But this also means that in some cases it Will actually leak memory and You should Always code so that you solve worst-case scenarios. Thats my opinion anyways.
Filip Ekberg
@Filip: assuming your own program invokes undefined behaviour? is that some evolved form of defensive programming?
Michael Foukarakis
+1 for humorous answer :D
Stowelly
+1 for being a correct. Talking about how `delete` and `delete[]` behaves in some specific implementation just gives the wrong idea. It's undefined behavior: don't do it.
jalf
I suppose the down-vote is because someone didn't believe C++ could make you pregnant? `:)`
sbi
A: 

Yes it will Leak.

You need to use delete [] for it to understand that it is an array and that it should follow the pointer and delete the underlying objects.

IF you just use delete myArrayPointer it will Only delete the actual pointer and not the things that it is pointing At.

Filip Ekberg
Wrong. I have worked with a compiler were it very definitely didn't leak when only PODs were involved. (And I might even be working nowadays. I didn't check. And I won't.)
sbi
But `delete ptr` deletes the thing pointed to by `ptr`, not `ptr` itself, so it is not *that* different to `delete[] ptr` which deletes the thing(s) pointed to by `ptr`. You can't be so definitive as "it will Leak". The behaviour is undefined so anything could happen.
Charles Bailey
As i Commented on another post here, if it is "Undefined" I would always assume worst case scenario. It feels like rolling a dice whenever you run the program. And yes, it deletes the thing it points to, but just the first one, it doesn't follow ( always that is ).
Filip Ekberg
A: 

It will usually not leak because in case of POD destructors are trivial and there's no need for invoking them so delete just deallocates memory occupied by the array. Memory deallocation requires just a pointer value so it will be returned to the heap. The array accopies a contiguous block of memory and so the deallocation can be sucessful just as if it was a deallocation of a single element.

But don't rely on this since it is undefined behaviour. Maybe it works allright, maybe something horrible happens, works on this compiler, doesn't work on another and many people thank you for planting an error.

See this answer for details.

sharptooth
Why was this downvoted I wonder...
sharptooth
Because `new T[]` may add an `sizeof` offset regardless of the POD-ness of T, in which case `delete[]` will compensate for this. `delete` would miss the header allocation block by a few bytes, interpreting an (possibly uninitialized) element count as a header, and cause unpredicatable heap corruption. Which of course shows up only when the boss looks.
MSalters
Sure, that's why the word *usually* is there. And heap corruption is not a leak.
sharptooth
`struct A { void operator delete[](void *p, size_t t) { } };` even though `struct A` is a `POD`, `new A[10]` will allocate and store that size, and `delete[]` will have to retrieve it and pass it to operator delete
Johannes Schaub - litb
A: 

For array of POD it will not leak (with the most compilers). For example, MSVC generates identical code for delete and delete[] for array of POD.

Personally, I think C/C++ could be without operator delete[]. Compiler knows object size and allocated memory size is known at runtime, thus it is very simple to know is a pointer array or not and dispose memory in a right way.

EDIT:

OK, guys. Can you test at your compiler and say whether it leak?

Try to think as a compiler developer. We have new, new[], delete, delete[]. Each new has its own delete. Seems perfect and complete. Let's see what is going on when you call delete[]?

1. call vector destructor for an object
2. actual free memory

What is destructor for POD? Nothing! So, calling delete for array of POD will not leak! Even if it breaks the standard. Even if it is not recommended.

EDIT2:

This is disassembly code generated by VS2008:

operator delete[]:
78583BC3  mov         edi,edi 
78583BC5  push        ebp  
78583BC6  mov         ebp,esp 
78583BC8  pop         ebp  
78583BC9  jmp         operator delete (78583BA3h)
Sergius
`delete[]` is definitely not some form of optimization. It's all about correctness.
sbi
Yes, but is is superfluous. People want to know whether it will leak and I answered. Why downvote?
Sergius
By the way, I like CORRECTNESS. But we discuss not it...
Sergius
@Sergius: I can't speak for the others, but I down-voted it because you said "For array of POD it will not leak" - even though you somewhat played this down later. What this does is _undefined_. Period. (There are reasonable assumptions from which one can deduce possible scenarios, but they definitely won't fit all compilers or even compiler versions, so making such statement just seems wrong to me.)
sbi
Well, I said "(with the most compilers)". But thanks anyway! I will be more careful in my statement.
Sergius
+1  A: 

For delete ptr, as others have pointed out, the behaviour is undefined. If you take a minute to compile and run the following:

#include <stdio.h>

static int counter = 0;

class A
{
    private:
     int val;
    public:
    A() {
     this->val = ++counter;
    }
    ~A() {
     printf("value %d\n", this->val);
    }

};

int main(int argc, char **argv)
{
    A *p = new A[10];
    delete p;
    printf("We're done here!\n");
}

with gcc, you'll witness the exact effect of delete on a memory chunk allocated with new[]. :-)

Now, remove the destructor I defined (A is now of a POD class type) and notice what happens.

Michael Foukarakis
@Michael, class A is not POD, this question is about POD
sat
I understand that, but seeing where the shit hits the fan will lead him/her to the correct conclusion. At least for gcc. Granted, it takes some thinking, but I'm not interested in the obvious. :P
Michael Foukarakis