Identify the memory leaks - c++

I'm trying to answer some past paper questions that I've been given for exam practice but not really sure on these two, any help be greatly appreciated. (Typed code up from image, think it's all right).
Q1: Identify the memory leaks in the C++ code below and explain how to fix them. [9 marks]
#include <string>
class Logger {
public:
static Logger &get_instance () {
static Logger *instance = NULL;
if (!instance){
instance = new Logger();
}
return *instance;
}
void log (std::string const &str){
// ..log string
}
private:
Logger(){
}
Logger(Logger const&) {
}
Logger& operator= (Logger const &) {
}
~Logger() {
}
};
int main(int argcv, char *argv[]){
int *v1 = new int[10];
int *v2 = new int[20];
Logger::get_instance() . log ("Program Started");
// .. do something
delete v1;
delete v2;
return 0;
}
My answer is that if main never finishes executing due to an early return or an exception being thrown that the deletes will never run causing the memory to never be freed.
I've been doing some reading and I believe an auto_ptr would solve the problems? Would this be as simple as changing lines to?? :
auto_ptr<int> v1 = new int[10];
auto_ptr<int> v2 = new int[20];
v1.release();
delete v1;
Q2: Why do virtual members require more memory than objects of a class without virtual members?
A: Because each virtual member requires a pointer to be stored also in a vtable requiring more space. Although this equates to very little increase in space.

Q1: Note that v1 and v2 are int pointers that refer to an array of 10 and 20, respectively. The delete operator does not match - ie, since it is an array, it should be
delete[] v1;
delete[] v2;
so that the whole array is freed. Remember to always match new[] and delete[] and new and delete
I believe you're already correct on Q2. The vtable and corresponding pointers that must be kept track of do increase the memory consumption.

Just to summarize:
the shown program has undefined behavior using incorrect form of delete, so talking about leaks for the execution is immaterial
if the previous was fixed, leaks wold come from:
new Logger(); // always
the other two new uses, if subsequent new throws or string ctor throws or the ... part in log throws.
to fix v1 and v2 auto_ptr is no good ad you allocated with new[]. you could use boost::auto_array or better make v array<int, 10> or at least vector<int>. And you absolutely don't use release() and then manual delete, but leade that to the smart pointer.
fixing instance is interesting. What is presented is called the 'leaky singleton' that is supposed to leak the instance. But be omnipresent after creation in case something wants to use it during program exit. If that was not intended, instance shall not be created using new, but be directly, being local static or namespace static.
the question is badly phrased comparing incompatible things. Assuming it is sanitized the answer is that a for a class with virtual members instances are (very likely) to carry an extra pointer to the VMT. Plus the the VMT itself has one entry per virtual member after some general overhead. The latter is indeed insignificant, but the former may be an issue, as a class with 1 byte of state may pick up a 8 byte pointer, and possibly another 7 bytes of padding.

Your first answer is correct to get credit, but what the examiner was probably looking for is the freeing up of Logger *instance
In the given code, memory for instance is allocated, but never deallocated.
The second answer looks good.

instance is never deleted and you need to use operator delete[] in main().

Q1:
few gotchyas -
singleton pattern is very dangerous, for example it is not thread safe, two threads could come in and create two classes - causing a memory leak, surround with EnterCriticalSection or some other thread sync mechanism, and still unsafe and not recommended to use.
singleton class does not release they memory, singleton should be ref counted to really act properly.
you're using a static variable inside the function, even worse than using a static member for the class.
you allocate with new [] and delete without the delete[]
I suspect your question is two things:
- free the singleton pointer
- use delete[]
In general however the process cleanup will clean the dangling stuff..
Q2:
your second question is right, because virtual members require a vtable which makes the class larger

Related

Why deleting pointer to list causes core dump [duplicate]

This is a question that's been nagging me for some time. I always thought that C++ should have been designed so that the delete operator (without brackets) works even with the new[] operator.
In my opinion, writing this:
int* p = new int;
should be equivalent to allocating an array of 1 element:
int* p = new int[1];
If this was true, the delete operator could always be deleting arrays, and we wouldn't need the delete[] operator.
Is there any reason why the delete[] operator was introduced in C++? The only reason I can think of is that allocating arrays has a small memory footprint (you have to store the array size somewhere), so that distinguishing delete vs delete[] was a small memory optimization.
It's so that the destructors of the individual elements will be called. Yes, for arrays of PODs, there isn't much of a difference, but in C++, you can have arrays of objects with non-trivial destructors.
Now, your question is, why not make new and delete behave like new[] and delete[] and get rid of new[] and delete[]? I would go back Stroustrup's "Design and Evolution" book where he said that if you don't use C++ features, you shouldn't have to pay for them (at run time at least). The way it stands now, a new or delete will behave as efficiently as malloc and free. If delete had the delete[] meaning, there would be some extra overhead at run time (as James Curran pointed out).
Damn, I missed the whole point of question but I will leave my original answer as a sidenote. Why we have delete[] is because long time ago we had delete[cnt], even today if you write delete[9] or delete[cnt], the compiler just ignores the thing between [] but compiles OK. At that time, C++ was first processed by a front-end and then fed to an ordinary C compiler. They could not do the trick of storing the count somewhere beneath the curtain, maybe they could not even think of it at that time. And for backward compatibility, the compilers most probably used the value given between the [] as the count of array, if there is no such value then they got the count from the prefix, so it worked both ways. Later on, we typed nothing between [] and everything worked. Today, I do not think delete[] is necessary but the implementations demand it that way.
My original answer (that misses the point):
delete deletes a single object. delete[] deletes an object array. For delete[] to work, the implementation keeps the number of elements in the array. I just double-checked this by debugging ASM code. In the implementation (VS2005) I tested, the count was stored as a prefix to the object array.
If you use delete[] on a single object, the count variable is garbage so the code crashes. If you use delete for an object array, because of some inconsistency, the code crashes. I tested these cases just now !
"delete just deletes the memory allocated for the array." statement in another answer is not right. If the object is a class, delete will call the DTOR. Just place a breakpoint int the DTOR code and delete the object, the breakpoint will hit.
What occurred to me is that, if the compiler & libraries assumed that all the objects allocated by new are object arrays, it would be OK to call delete for single objects or object arrays. Single objects just would be the special case of an object array having a count of 1. Maybe there is something I am missing, anyway.
Since everyone else seems to have missed the point of your question, I'll just add that I had the same thought some year ago, and have never been able to get an answer.
The only thing I can think of is that there's a very tiny bit of extra overhead to treat a single object as an array (an unnecessary "for(int i=0; i<1; ++i)" )
Adding this since no other answer currently addresses it:
Array delete[] cannot be used on a pointer-to-base class ever -- while the compiler stores the count of objects when you invoke new[], it doesn't store the types or sizes of the objects (as David pointed out, in C++ you rarely pay for a feature you're not using). However, scalar delete can safely delete through base class, so it's used both for normal object cleanup and polymorphic cleanup:
struct Base { virtual ~Base(); };
struct Derived : Base { };
int main(){
Base* b = new Derived;
delete b; // this is good
Base* b = new Derived[2];
delete[] b; // bad! undefined behavior
}
However, in the opposite case -- non-virtual destructor -- scalar delete should be as cheap as possible -- it should not check for number of objects, nor for the type of object being deleted. This makes delete on a built-in type or plain-old-data type very cheap, as the compiler need only invoke ::operator delete and nothing else:
int main(){
int * p = new int;
delete p; // cheap operation, no dynamic dispatch, no conditional branching
}
While not an exhaustive treatment of memory allocation, I hope this helps clarify the breadth of memory management options available in C++.
Marshall Cline has some info on this topic.
delete [] ensures that the destructor of each member is called (if applicable to the type) while delete just deletes the memory allocated for the array.
Here's a good read: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=287
And no, array sizes are not stored anywhere in C++. (Thanks everyone for pointing out that this statement is inaccurate.)
I'm a bit confused by Aaron's answer and frankly admit I don't completely understand why and where delete[] is needed.
I did some experiments with his sample code (after fixing a few typos). Here are my results.
Typos:~Base needed a function body
Base *b was declared twice
struct Base { virtual ~Base(){ }>; };
struct Derived : Base { };
int main(){
Base* b = new Derived;
delete b; // this is good
<strike>Base</strike> b = new Derived[2];
delete[] b; // bad! undefined behavior
}
Compilation and execution
david#Godel:g++ -o atest atest.cpp
david#Godel: ./atest
david#Godel: # No error message
Modified program with delete[] removed
struct Base { virtual ~Base(){}; };
struct Derived : Base { };
int main(){
Base* b = new Derived;
delete b; // this is good
b = new Derived[2];
delete b; // bad! undefined behavior
}
Compilation and execution
david#Godel:g++ -o atest atest.cpp
david#Godel: ./atest
atest(30746) malloc: *** error for object 0x1099008c8: pointer being freed was n
ot allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
Of course, I don't know if delete[] b is actually working in the first example; I only know it does not give a compiler error message.

Pointer in a class

I have the following below code snippet
class test{
private:
int *ptr;
public:
test(int *myptr){
ptr = myptr;
}
~test(){
delete ptr;
}
};
int main(){
int* myptr = new int;
*myptr = 10;
test obj(myptr);
delete myptr;
}
Is there a memory leak happening in this program, if I dont do a new to pointer in the class will space be allocated for that pointer?
Rule of thumb for dealing with allocating member: every new/new[] should be paired with exactly one delete/delete[]. If you are missing the delete, then you have a memory leak (you have allocated memory that you never clean up). If you are delete-ing multiples times, as you are doing in this code example, you will have memory corruption issues.
How are you delete-ing multiple times? In main(), you allocate a pointer:
int* myptr = new int;
You give a copy of that pointer to your test object, obj. Then, at the end of the scope we have:
{
// ...
delete myptr;
~test(); // implicit, which also does delete myptr
}
Only one of those two places should be responsible for delete-ing the pointer. Which one is based on the semantics of your code. Does test own the pointer? In which case, it should delete it but main() should not. Does it simply observe the pointer? In which case, it should not delete it. With C++11, we have new smart pointers to express this idea better.
I'd encourage you to browse the definitive C++ book list as concepts like this are very crucial to understanding C++ but also very difficult to explain properly in a short Q&A format.
You should only delte a pointer once in ~test() or delete directly
*** Error in `./a.out': double free or corruption (fasttop): 0x08d13a10 ***
Consider using std::shared_ptr<int> or std::unique_ptr<int>, since direct memory management is discouraged in modern C++ unless you've a reason to do so.
You can read about semantics differences of smart pointers here, and the reference for them is here.
It will crash when exit main function, a allocated in heap memory can't be release two times
What will happen in your instance is that the pointer will be given to delete in main(), then the same pointer value will be given a second time to delete in the destructor of obj. This is undefined behaviour, so it might work, or it might not, in any case, it isn't guaranteed to work, and therefore such a construct should not be used.
Ordinarily you would establish ownership rules, e.g. whether the constructor “takes ownership” (and is therefore responsible for freeing resources) is up to you, but typically, and especially in modern C++, ownership semantics can be clearly achieved by using std::unique_ptr and std::shared_ptr.
Most importantly, whichever method you use to determine ownership, make sure you are consistent! Avoid complicated ownership semantics, as it will make it much more difficult to detect memory-related issues (or more generally, resource-related issues).
Contrary to what other people have said: you do not delete pointers in C++, but objects.
What's the difference?
Let's simplify your code a bit:
int *myptr = new int; // 1
int *ptr = myptr; // 2
delete myptr; // 3
delete ptr; // 4
As far as the usage of new and delete is concerned, this is the same code - I've just removed the class, since it's not relevant to the point here.
This code does the following:
new int allocates an int, and returns its address. The address is then stored in myptr.
The address is copied to ptr. Both ptr and myptr contain the address of the int that was just allocated.
The int is deallocated.
The int is deallocated... but it was already deallocated? Oops!
If you're lucky, your program will crash at this point.
delete myptr; has nothing to do with the variable myptr, except that myptr holds the address of the thing to delete.
It doesn't even have to be a variable - you could do delete new int; (although it wouldn't be very useful) or delete someFunctionThatReturnsAnAddress();, or int *p = 1 + new int[2]; delete [] (p - 1);.
Your class has only a reference of the allocated integer. Consider to declare it int const* ptr, then you cant delete it inside the class.
You should remove delete ptr from the destructor.
Usually the scope which is allocating something is responsible for freeing it. In your case the main routine is allocating and has to free.
For your question "Is there a memory leak happening in this program", the answer is No, but an exception is rasing.
Your code logic is not good, you should delete the pointer at where it was created. In this example, you shouldn't delete ptr in destructor function.

Stack Overflow when deleting this Pointer

I have the following code and I get stack overflow error can anyone please explain me What's wrong here. from my understanding this pointer points to current object so why I cant delete it in a destructor;
class Object
{
private:
static int objCount;
public:
int getCount()
{
int i =10;
return i++;
}
Object()
{
cout<< "Obj Created = "<<++objCount<<endl;
cout <<endl<<this->getCount()<<endl;
}
~Object()
{
cout<<"Destructor Called\n"<<"Deleted Obj="<<objCount--<<endl;
delete this;
}
};
int Object::objCount = 0;
int _tmain(int argc, _TCHAR* argv[])
{
{
Object obj1;
}
{
Object *obj2 = new Object();
}
getchar();
return 0;
}
You're doing delete this; in your class's destructor.
Well, delete calls the class's destructor.
You're doing delete this; in your class's destructor.
...
<!<!<!Stack Overflow!>!>!>
(Sorry guys I feel obliged to include this... this might probably spoil it sorrrryyyy!
Moral of the boring story, don't do delete this; on your destructor (or don't do it at all!)
Do [1]
Object *obj = new Object();
delete obj;
or much better, just
Object obj;
[1]#kfsone's answer more accurately points out that the stack overflow was actually triggered by obj1's destructor.
'delete this' never makes sense. Either you're causing an infinite recursion, as here, or you're deleting an object while it is still in use by somebody else. Just remove it. The object is already being deleted: that's why you're in the destructor.
The crash you are having is because of the following statement:
{
Object obj1;
}
This allocates an instance of "Object" on the stack. The scope you created it in ends, so the object goes out of scope, so the destructor (Object::~Object) is invoked.
{
Object obj1;
// automatic
obj1.~Object();
}
This means that the next instruction the application will encounter is
delete this;
There are two problems right here:
delete calls the object's destructor, so your destructor indirectly calls your destructor which indirectly calls your destructor which ...
After the destructor call, delete attempts to return the object's memory to the place where new obtains it from.
By contrast
{
Object *obj2 = new Object();
}
This creates a stack variable, obj2 which is a pointer. It allocates memory on the heap to store an instance of Object, calls it's default constructor, and stores the address of the new instance in obj2.
Then obj2 goes out of scope and nothing happens. The Object is not released, nor is it's destructor called: C++ does not have automatic garbage collection and does not do anything special when a pointer goes out of scope - it certainly doesn't release the memory.
This is a memory leak.
Rule of thumb: delete calls should be matched with new calls, delete [] with new []. In particular, try to keep new and delete in matching zones of authority. The following is an example of mismatched ownership/authority/responsibility:
auto* x = xFactory();
delete x;
Likewise
auto* y = new Object;
y->makeItStop();
Instead you should prefer
// If you require a function call to allocate it, match a function to release it.
auto* x = xFactory();
xTerminate(x); // ok, I just chose the name for humor value, Dr Who fan.
// If you have to allocate it yourself, you should be responsible for releasing it.
auto* y = new Object;
delete y;
C++ has container classes that will manage object lifetime of pointers for you, see std::shared_ptr, std::unique_ptr.
There are two issues here:
You are using delete, which is generally a code smell
You are using delete this, which has several issues
Guideline: You should not use new and delete.
Rationale:
using delete explicitly instead of relying on smart pointers (and automatic cleanup in general) is brittle, not only is the ownership of a raw pointer unclear (are you sure you should be deleting it ?) but it is also unclear whether you actually call delete on every single codepath that needs it, especially in the presence of exceptions => do your sanity (and that of your fellows) a favor, don't use it.
using new is also error-prone. First of all, are you sure you need to allocate memory on the heap ? C++ allows to allocate on the stack and the C++ Standard Library has containers (vector, map, ...) so the actual instances where dynamic allocation is necessary are few and far between. Furthermore, as mentioned, if you ever reach for dynamic allocation you should be using smart pointers; in order to avoid subtle order of execution issues it is recommend you use factory functions: make_shared and make_unique (1) to build said smart pointers.
(1) make_unique is not available in C++11, only in C++14, it can trivially be implemented though (using new, of course :p)
Guideline: You shall not use delete this.
Rationale:
Using delete this means, quite literally, sawing off the branch you are sitting on.
The argument to delete should always be a dynamically allocated pointer; therefore should you inadvertently allocate an instance of the object on the stack you are most likely to crash the program.
The execution of the method continues past this statement, for example destructors of local objects will be executed. This is like walking on the ghost of the object, don't look down!
Should a method containing this statement throw an exception or report an error, it is difficult to appraise whether the object was successfully destroyed or not; and trying again is not an option.
I have seen several example of usage, but none that could not have used a traditional alternative instead.

double free without any dynamic memory allocation

In general, what could cause a double free in a program that is does not contain any dynamic memory allocation?
To be more precise, none of my code uses dynamic allocation. I'm using STL, but it's much more likely to be something I did wrong than for it to be a broken implmentation of G++/glibc/STL.
I've searched around trying to find an answer to this, but I wasn't able to find any example of this error being generated without any dynamic memory allocations.
I'd love to share the code that was generating this error, but I'm not permitted to release it and I don't know how to reduce the problem to something small enough to be given here. I'll do my best to describe the gist of what my code was doing.
The error was being thrown when leaving a function, and the stack trace showed that it was coming from the destructor of a std::vector<std::set<std::string>>. Some number of elements in the vector were being initialized by emplace_back(). In a last ditch attempt, I changed it to push_back({{}}) and the problem went away. The problem could also be avoided by setting the environment variable MALLOC_CHECK_=2. By my understanding, that environment variable should have caused glibc to abort with more information rather than cause the error to go away.
This question is only being asked to serve my curiosity, so I'll settle for a shot in the dark answer. The best I have been able to come up with is that it was a compiler bug, but it's always my fault.
In general, what could cause a double free in a program that is does not contain any dynamic memory allocation?
Normally when you make a copy of a type which dynamically allocates memory but doesn't follow rule of three
struct Type
{
Type() : ptr = new int(3) { }
~Type() { delete ptr; }
// no copy constructor is defined
// no copy assign operator is defined
private:
int * ptr;
};
void func()
{
{
std::vector<Type> objs;
Type t; // allocates ptr
objs.push_back(t); // make a copy of t, now t->ptr and objs[0]->ptr point to same memory location
// when this scope finishes, t will be destroyed, its destructor will be called and it will try to delete ptr;
// objs go out of scope, elements in objs will be destroyed, their destructors are called, and delete ptr; will be executed again. That's double free on same pointer.
}
}
I extracted a presentable example showcasing the fault I made that led to the "double free or corruption" runtime error. Note that the struct doesn't explicitly use any dynamic memory allocations, however internally std::vector does (as its content can grow to accommodate more items). Therefor, this issue was a bit hard to diagnose as it doesn't violate 'the rule of 3' principle.
#include <vector>
#include <string.h>
typedef struct message {
std::vector<int> options;
void push(int o) { this->options.push_back(o); }
} message;
int main( int argc, const char* argv[] )
{
message m;
m.push(1);
m.push(2);
message m_copy;
memcpy(&m_copy, &m, sizeof(m));
//m_copy = m; // This is the correct method for copying object instances, it calls the default assignment operator generated 'behind the scenes' by the compiler
}
When main() returns m_copy is destroyed, which calls the std::vector destructor. This tries to delete memory that was already freed when the m object was destroyed.
Ironically, I was actually using memcpy to try and achieve a 'deep copy'. This is where the fault lies in my case. My guess is that by using the assignment operator, all the members of message.options are actually copied to "newly allocated memory" whereas memcpy would only copy those members that were allocated at compile time (e.g. a uint32_t size member). See Will memcpy or memmove cause problems copying classes?. Obviously this also applies to structs with non-fundamental typed members (as is the case here).
Maybe you also copied a std::vector incorrectly and saw the same behavior, maybe you didn't. In the end, it was my entirely my fault :).

Why do we even need the "delete[]" operator?

This is a question that's been nagging me for some time. I always thought that C++ should have been designed so that the delete operator (without brackets) works even with the new[] operator.
In my opinion, writing this:
int* p = new int;
should be equivalent to allocating an array of 1 element:
int* p = new int[1];
If this was true, the delete operator could always be deleting arrays, and we wouldn't need the delete[] operator.
Is there any reason why the delete[] operator was introduced in C++? The only reason I can think of is that allocating arrays has a small memory footprint (you have to store the array size somewhere), so that distinguishing delete vs delete[] was a small memory optimization.
It's so that the destructors of the individual elements will be called. Yes, for arrays of PODs, there isn't much of a difference, but in C++, you can have arrays of objects with non-trivial destructors.
Now, your question is, why not make new and delete behave like new[] and delete[] and get rid of new[] and delete[]? I would go back Stroustrup's "Design and Evolution" book where he said that if you don't use C++ features, you shouldn't have to pay for them (at run time at least). The way it stands now, a new or delete will behave as efficiently as malloc and free. If delete had the delete[] meaning, there would be some extra overhead at run time (as James Curran pointed out).
Damn, I missed the whole point of question but I will leave my original answer as a sidenote. Why we have delete[] is because long time ago we had delete[cnt], even today if you write delete[9] or delete[cnt], the compiler just ignores the thing between [] but compiles OK. At that time, C++ was first processed by a front-end and then fed to an ordinary C compiler. They could not do the trick of storing the count somewhere beneath the curtain, maybe they could not even think of it at that time. And for backward compatibility, the compilers most probably used the value given between the [] as the count of array, if there is no such value then they got the count from the prefix, so it worked both ways. Later on, we typed nothing between [] and everything worked. Today, I do not think delete[] is necessary but the implementations demand it that way.
My original answer (that misses the point):
delete deletes a single object. delete[] deletes an object array. For delete[] to work, the implementation keeps the number of elements in the array. I just double-checked this by debugging ASM code. In the implementation (VS2005) I tested, the count was stored as a prefix to the object array.
If you use delete[] on a single object, the count variable is garbage so the code crashes. If you use delete for an object array, because of some inconsistency, the code crashes. I tested these cases just now !
"delete just deletes the memory allocated for the array." statement in another answer is not right. If the object is a class, delete will call the DTOR. Just place a breakpoint int the DTOR code and delete the object, the breakpoint will hit.
What occurred to me is that, if the compiler & libraries assumed that all the objects allocated by new are object arrays, it would be OK to call delete for single objects or object arrays. Single objects just would be the special case of an object array having a count of 1. Maybe there is something I am missing, anyway.
Since everyone else seems to have missed the point of your question, I'll just add that I had the same thought some year ago, and have never been able to get an answer.
The only thing I can think of is that there's a very tiny bit of extra overhead to treat a single object as an array (an unnecessary "for(int i=0; i<1; ++i)" )
Adding this since no other answer currently addresses it:
Array delete[] cannot be used on a pointer-to-base class ever -- while the compiler stores the count of objects when you invoke new[], it doesn't store the types or sizes of the objects (as David pointed out, in C++ you rarely pay for a feature you're not using). However, scalar delete can safely delete through base class, so it's used both for normal object cleanup and polymorphic cleanup:
struct Base { virtual ~Base(); };
struct Derived : Base { };
int main(){
Base* b = new Derived;
delete b; // this is good
Base* b = new Derived[2];
delete[] b; // bad! undefined behavior
}
However, in the opposite case -- non-virtual destructor -- scalar delete should be as cheap as possible -- it should not check for number of objects, nor for the type of object being deleted. This makes delete on a built-in type or plain-old-data type very cheap, as the compiler need only invoke ::operator delete and nothing else:
int main(){
int * p = new int;
delete p; // cheap operation, no dynamic dispatch, no conditional branching
}
While not an exhaustive treatment of memory allocation, I hope this helps clarify the breadth of memory management options available in C++.
Marshall Cline has some info on this topic.
delete [] ensures that the destructor of each member is called (if applicable to the type) while delete just deletes the memory allocated for the array.
Here's a good read: http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=287
And no, array sizes are not stored anywhere in C++. (Thanks everyone for pointing out that this statement is inaccurate.)
I'm a bit confused by Aaron's answer and frankly admit I don't completely understand why and where delete[] is needed.
I did some experiments with his sample code (after fixing a few typos). Here are my results.
Typos:~Base needed a function body
Base *b was declared twice
struct Base { virtual ~Base(){ }>; };
struct Derived : Base { };
int main(){
Base* b = new Derived;
delete b; // this is good
<strike>Base</strike> b = new Derived[2];
delete[] b; // bad! undefined behavior
}
Compilation and execution
david#Godel:g++ -o atest atest.cpp
david#Godel: ./atest
david#Godel: # No error message
Modified program with delete[] removed
struct Base { virtual ~Base(){}; };
struct Derived : Base { };
int main(){
Base* b = new Derived;
delete b; // this is good
b = new Derived[2];
delete b; // bad! undefined behavior
}
Compilation and execution
david#Godel:g++ -o atest atest.cpp
david#Godel: ./atest
atest(30746) malloc: *** error for object 0x1099008c8: pointer being freed was n
ot allocated
*** set a breakpoint in malloc_error_break to debug
Abort trap: 6
Of course, I don't know if delete[] b is actually working in the first example; I only know it does not give a compiler error message.