Using a base class as a safe container for pointers - c++

So I was looking at this question Memory Allocation Exception in Constructor where my boss states in his beautiful answer that the destructor will not be called.
Which makes me wonder,
If I were to write
struct XBase
{
int* a;
char* b;
float* c;
XBase() : a(nullptr), b(nullptr), c(nullptr) {}
~XBase()
{
delete[] a; delete[] b; delete[] c;
}
};
and
struct X : XBase
{
X() {
a = new int[100];
b = new char[100];
c = new float[100];
}
}
Then, if the allocation of c fails (with an exception being thrown), then the destructor of XBase would be called, since the base class has been constructed.
And no memory leak?
Am I correct?

You are right; this will work, because:
By the time X constructor body is executed, XBase is already constructed, and its destructor will be called.
Doing delete or delete[] on null pointers is perfectly valid, and does nothing.
So, if the allocation of a, b or c fails, the destructor of XBase will deallocate everything.
But, obviously, this design makes you write much more code that needed, since you can simply use std::vector or std::unique_ptr<T[]>.

Just to have a formal version here to back up the claims,
§ 15.2/2
An object of any storage duration whose initialization or destruction is terminated by an exception will have destructors executed for all of its fully constructed subobjects [...].

If you're concerned about the memory allocation failing, I would put it in a separate method, like a Build or Create. You could then let the destructor handle it if it has been initialized (but definitely check pointer before blindly delete-ing.
Another solution is smart pointers, which are not designed to fit this case necessarily, but do automatically deallocate their contents.

Related

Does the synthesized destructor destroy the memory allocated on the heap?

I have a class without a destructor and a constructor like this:
class Foo {
public:
Foo(int a) : p(new int(a)) {}
private:
int *p;
};
{
Foo a(4);
}
After this block of code will the memory allocated on the heap be released ?
Or do i have to explicitly provide a destructor like this:
class Foo {
public:
Foo(int a) : p(new int(a)) {}
~Foo();
private:
int *p;
};
Foo::~Foo() {
delete p;
}
Any memory we allocate on the heap using new must always be freed by using the keyword delete.
So,you have to explicitly free the memory allocated by new on the heap using the keyword delete as you did in the destructor. The synthesized destructor will not do it for you.
Note if you don't want to deal with memory management by yourself then you can use smart pointers. That way you will not have to use delete explicitly by yourself because the destructor corresponding to the smart pointer will take care of freeing up the memory. This essentially means if the data member named p was a smart pointer instead of a normal(built in) pointer, then you don't have to write delete p in the destructor of your class Foo.
As an additional answer to Anoop's correct one:
Just try to "emphasize" with the compiler and the runtime. If the destructor call occurs, how should the environment decide whether to call delete on a pointer or not? It has no chance to determine this and it's actually not its job by language design (partially in contrast to the C# and Java philosophy). The pointer could be a non-owning one as well, whose referred dynamically allocated storage should survive your particular destructor call, even possible for cases where your class was the allocator (bad design in general but allowed).
The destructor context just "sees" the members and for this case, that's solely a pointer a priori, not a possibly further dynamically allocated ressource.
Please try to get familiar with the important RAII -technique, that is not only relevant to dynamic memory allocation.

c++ operator new how this works internally

For example I have a simple code:
class B
{
};
class A
{
B b;
public:
A()
{
throw 1;
}
};
int main()
{
A* a = 0;
try
{
a = new A;
}
catch (int)
{
}
}
Constructor A throws exception, then destructor will not be called. But destructor for B will be called. Memory in the heap will not be allocated. My question how this works internally? What will be first: constructing A or allocating memory in the heap? So, if allocating is the first, how deallocating will be handled if there are exception? Othervise, if constructing A is the first, how it's copiing to the heap?
The memory is allocated.
The constructor of A is called.
The constructor of A calls the constructor of B.
The constructor of A throws.
As a part of the standard exception handling procedure, the destructor of B is called (RAII at work).
The stack unwinds to the caller (main).
The memory is deallocated (because the object wasn't constructed successfully).
The destructor of A isn't called because the object was not fully constructed. However, the members which were fully constructed are still destroyed.
The memory is deallocated automatically in pretty much the same way as local variables are destroyed when the control leaves the block. If you're familiar with Java and/or C#, think of it as an invisible try-finally construct. Or a series of such constructs.
What will be first: constructing A or allocating memory in the heap?
Unless there's memory, there's no space in which the object can be constructed. Memory allocation always goes first; then the code proceeds with initialization. This applies to all kinds of memory allocations, not only of the dynamic variety, because constructors need to have a valid address of this before they start initializing the object.
If allocating is the first, how deallocating will be handled if there are exception?
The compiler emits special code that handles the "magic" here. This code will run destructors for all base classes, and for members, such as B, that have been fully constructed by the time the code entered A's constructor.

When we're starting to overwrite memory has lifetime of an object has ended yet?

I cannot resolve the following issue by myself:
Suppose we are reusing a memory in a following way:
struct A
{
int a;
A(){ }
~A(){ }
};
struct B : A
{
int b;
B(){ }
~B(){ }
};
A *a = (A*) malloc(sizeof(A) + sizeof(B));
B *b = new (a) B; //Constructor of B is calling
The lifetime of object reffered to by a has ended before the constructor of B is starting to call or it has ended when the constructor of B has finished?
You try to use the placement new operator to initialize b. This operator does not call the destructor of class A first (a), but initializes a new one into the memory pointed to by a. This is problematic (as mentioned in the comment), because the sizeof(B) is greater than sizeof(A) and you allocated only sizeof(A) at the pointer a. So it is undefined behavior.
The lifetime of the object a formally does not end. You get something like:
class A { int a; };
void* p = malloc(sizeof(A));
A* a1 = new (p) A();
A* a2 = new (p) A();
I think, you will get something like double called destructor on the same memory, but that is something compiler-implementation specific. I don't think, that the standard does say anything about this.
As soon as you enter the constructor of B, a is not pointing to an object A any more.
The reason is that even before the first instruction of the constructor of an object the runtime already has done the VMT, base sub-objects and member initialization.
Also if the constructor of B doesn't terminate because of an exception the memory has already been used anyway and another object eventually present at the same memory address doesn't exist any more.
In other words just don't do that... in C++ objects are not just a pile of bytes and they have rights; for example the right of having their destructor called ;-)
The standard from the relevant section (3.8) says,
The lifetime of an object of type T ends when:
- if T is a class type with a non-trivial destructor (12.4), the destructor call starts, or
- the storage which the object occupies is reused or released.
I interpret to mean that the life time of the object pointed to by a ends when members of B are initialized. Until that happens, the storage is not reused.
The lifetime of a ends when you delete it and not before - since forcing two different objects to occupy the same space this way is itself undefined behaviour and definitely not recommended your compiler may or may not treat that memory as available for reuse and overwrite b.
If you need to have two objects occupying the same location, e.g.: Message Variants or you are trying to write your own debugger then you should use a union type.
The other reason that you are not recommended to do this sort of thing is that you will create a maintenance nightmare. e.g. later in your code you could have:
b.b = 3
while (a.a > 0) {
b.b--;
}

handling failing constructors

I am reading failing constructors from C++ FAQ and don't understand the following code.
void f()
{
X x; ← if X::X() throws, the memory for x itself will not leak
Y* p = new Y(); ← if Y::Y() throws, the memory for *p itself will not leak
}
How is it possible that the memory pointed to by p will not leak if the constructor throws? I assumed the sequence is as follows.
Memory is allocated for object Y.
Y's constructor is called.
Y's constructor throws and memory pointed to by p leaks.
If Y's constructor throws, then the stack is unwound, including deleting the memory allocated for Y.
The problems arise primarily when/if you have more than one object to deal with. For example:
void f() {
X *x = new X();
Y *y = new Y();
}
Now, if the new X() part succeeds, but the new Y() part fails, the memory allocated for y will be deleted, but x will not be destroyed, and its memory will be leaked. You can work around this problem with try blocks, if you really insist:
try {
X *x = new X();
Y * y = new Y();
}
catch (y_construction_failed) {
delete x;
}
The big problem with this is that you have to nest the try blocks if you have more than two items, so if you need, say, half a dozen local variables, it's going to be deeply nested and excruciatingly ugly.
You will run into a similar problem having a function void f(X*, Y*) and calling f(new X(), new Y()). If one of the new calls succeeds and the other fails you have a memory leak. To resolve it you might create additional functions 'X* make_X()' and 'Y* make_Y()' returning pointers. Now, f(make_X(), make_Y()) is safe. (And after going that far, you might use smart pointers)
It's important to notice that even though the object is deleted, its destructor is not called in this case.
This makes sense, since an exception during construction indicates that the object was never fully constructed (ie. its class invariants have not been established), so calling the destructor could be dangerous.
The downside of this is that if the constructor performs actions that require cleanup which would normally be performed by the destructor, it is now the constructor's responsibility to perform this cleanup in case of exceptions. Take the following example:
class C {
private:
int* p1;
int* p2;
public:
C() : p1(new int()), p2(new int()) {}
~C() { delete p1; delete p2; }
};
If the allocation p2 throws, the memory already allocated for p1 will leak. It is your responsibility as a programmer to write constructors in a way that this cannot happen.
The easiest way to achieve this is by delegating the resource management responsibilities to a RAII container class like unique_ptr. That way, no class is responsible for managing more than one resource and scenarios like the one outlined above can no longer occur.

Who deletes the memory allocated during a "new" operation which has exception in constructor?

I really can't believe I couldn't find a clear answer to this...
How do you free the memory allocated after a C++ class constructor throws an exception, in the case where it's initialised using the new operator. E.g.:
class Blah
{
public:
Blah()
{
throw "oops";
}
};
void main()
{
Blah* b = NULL;
try
{
b = new Blah();
}
catch (...)
{
// What now?
}
}
When I tried this out, b is NULL in the catch block (which makes sense).
When debugging, I noticed that the conrol enters the memory allocation routine BEFORE it hits the constructor.
This on the MSDN website seems to confirm this:
When new is used to allocate memory
for a C++ class object, the object's
constructor is called after the memory
is allocated.
So, bearing in mind that the local variable b is never assigned (i.e. is NULL in the catch block) how do you delete the allocated memory?
It would also be nice to get a cross platform answer on this. i.e., what does the C++ spec say?
CLARIFICATION: I'm not talking about the case where the class has allocated memory itself in the c'tor and then throws. I appreciate that in those cases the d'tor won't be called. I'm talking about the memory used to allocate THE object (Blah in my case).
You should refer to the similar questions here and here.
Basically if the constructor throws an exception you're safe that the memory of the object itself is freed again. Although, if other memory has been claimed during the constructor, you're on your own to have it freed before leaving the constructor with the exception.
For your question WHO deletes the memory the answer is the code behind the new-operator (which is generated by the compiler). If it recognizes an exception leaving the constructor it has to call all the destructors of the classes members (as those have already been constructed successfully prior calling the constructor code) and free their memory (could be done recursively together with destructor-calling, most probably by calling a proper delete on them) as well as free the memory allocated for this class itself. Then it has to rethrow the catched exception from the constructor to the caller of new.
Of course there may be more work which has to be done but I cannot pull out all the details from my head because they are up to each compiler's implementation.
If an object cannot complete destruction because the constructor throws an exception, the first thing to happen (this happens as part of the constructor's special handling) is that all member variables to have been constructed are destroyed - if an exception is thrown in the initializer list, this means that only elements for which the initializer has completed are destroyed.
Then, if the object was being allocated with new, the appropriate deallocation function (operator delete) is called with the same additional arguments that were passed to operator new. For instance, new (std::nothrow) SomethingThatThrows() will allocate memory with operator new (size_of_ob, nothrow), attempt to construct SomethingThatThrows, destroy any members that were successfully constructed, then call operator delete (ptr_to_obj, nothrow) when an exception is propagated - it won't leak memory.
What you have to be careful is allocating several objects in succession - if one of the later ones throws, the previous ones will not be automatically be deallocated. The best way around this is with smart pointers, because as local objects their destructors will be called during stack unwinding, and their destructors will properly deallocate memory.
If the Constructor throws the memory allocated for the object is auto-magically returned to the system.
Note the destructor of the class that threw will not be called.
But the destructor of any base class (where the base constructor has completed) will also be called.
Note:
As most other people have noted members may need some clean up.
Members that have been fully initialized will have their destructors called, but if you have any RAW pointer members that you own (ie delete in the destructor) you will have to do some clean up before you do the throw (another reason not to use owned RAW pointers in your class).
#include <iostream>
class Base
{
public:
Base() {std::cout << "Create Base\n";}
~Base() {std::cout << "Destroy Base\n";}
};
class Deriv: public Base
{
public:
Deriv(int x) {std::cout << "Create Deriv\n";if (x > 0) throw int(x);}
~Deriv() {std::cout << "Destroy Deriv\n";}
};
int main()
{
try
{
{
Deriv d0(0); // All constructors/Destructors called.
}
{
Deriv d1(1); // Base constructor and destructor called.
// Derived constructor called (not destructor)
}
}
catch(...)
{
throw;
// Also note here.
// If an exception escapes main it is implementation defined
// whether the stack is unwound. By catching in main() you force
// the stack to unwind to this point. If you can't handle re-throw
// so the system exception handling can provide the appropriate
// error handling (such as user messages).
}
}
From the C++ 2003 Standard 5.3.4/17 - New:
If any part of the object initialization described above terminates by throwing an exception and a suitable deallocation function can be found, the deallocation function is called to free the memory in which the object was being constructed, after which the exception continues to propagate in the context of the new-expression. If no unambiguous matching deallocation function can be found, propagating the exception does not cause the object’s memory to be freed. [Note: This is appropriate when the called allocation function does not allocate memory; otherwise, it is likely to result in a memory leak. ]
So there may or may not be a leak - it depends on whether an appropriate deallocator can be found (which is normally the case, unless operator new/delete have been overridden).In the case where there's a suitable deallocator, the compiler is responsible for wiring in a call to it if the constructor throws.
Note that this is more or less unrelated to what happens to resources acquired in the constructor, which is what my first attempt at an answer discussed - and is a question that is discussed in many FAQs, articles, and postings.
The long and short of it is that if you haven't made any allocations of other entities in you object(as in your example) then the memory that was allocated will be deleted automatically. However, any new statements(or anything else that directly manages memory) needs to be handled in a catch statement in the constructor, Otherwise the object is deleted without deleting it's subsequent allocations and you, my friend, have a leak.
Quoted from C++ FAQ (parashift.com):
[17.4] How should I handle resources if my constructors may throw
exceptions?
Every data member inside your object should clean up its own mess.
If a constructor throws an exception, the object's destructor is not
run. If your object has already done something that needs to be undone
(such as allocating some memory, opening a file, or locking a
semaphore), this "stuff that needs to be undone" must be remembered
by a data member inside the object.
For example, rather than allocating memory into a raw Fred* data
member, put the allocated memory into a "smart pointer" member object,
and the destructor of this smart pointer will delete the Fred
object when the smart pointer dies. The template std::auto_ptr is an
example of such as "smart pointer." You can also write your own
reference counting smart pointer. You can also use smart pointers
to "point" to disk records or objects on other machines.
By the way, if you think your Fred class is going to be allocated
into a smart pointer, be nice to your users and create a typedef
within your Fred class:
#include <memory>
class Fred {
public:
typedef std::auto_ptr<Fred> Ptr;
...
};
That typedef simplifies the syntax of all the code that uses your
objects: your users can say Fred::Ptr instead of
std::auto_ptr<Fred>:
#include "Fred.h"
void f(std::auto_ptr<Fred> p); // explicit but verbose
void f(Fred::Ptr p); // simpler
void g()
{
std::auto_ptr<Fred> p1( new Fred() ); // explicit but verbose
Fred::Ptr p2( new Fred() ); // simpler
...
}
The problem described is as old as the road to Rome, to use a Dutch saying. I have worked out the problem and a memory allocation for an object that might throw an exception looks as follows:
try
{
std::string *l_string =
(_heap_cleanup_tpl<std::string>(&l_string),
new std::string(0xf0000000, ' '));
delete l_string;
}
catch(std::exception &)
{
}
Before the actual call to the new-operator, a nameless (temporary) object is created, which receives the address of the allocated memory through a user-defined new-operator (see the rest of this answer). In case of normal programme execution, the temporary object passes the result of the new-operator (the newly created and fully constructed object, in our case a very very very long string) to the variable l_string. In case of an exception, the value is not passed on, but the destructor of the temporary object deletes the memory (without ofcourse calling the destructor of the main object).
It is a bit fuzzy way of dealing with the issue, but it works. Problems may arise because this solution requires a user-defined new-operator and a user-defined delete-operator to go allong with it. The user-defined new/delete-operators would have to call the C++-standard library's implementation of new/delete-operators, but I have left that out for briefity and relied on malloc() and free() instead.
It is not the final answer, but I think it is worth working this one out.
PS: There was an 'undocumented' feature in the code below, so I have made an improvement.
The code for the temporary object is as follows:
class _heap_cleanup_helper
{
public:
_heap_cleanup_helper(void **p_heap_block) :
m_heap_block(p_heap_block),
m_previous(m_last),
m_guard_block(NULL)
{
*m_heap_block = NULL;
m_last = this;
}
~_heap_cleanup_helper()
{
if (*m_heap_block == NULL) operator delete(m_guard_block);
m_last = m_previous;
}
void **m_heap_block, *m_guard_block;
_heap_cleanup_helper *m_previous;
static _heap_cleanup_helper *m_last;
};
_heap_cleanup_helper *_heap_cleanup_helper::m_last;
template <typename p_alloc_type>
class _heap_cleanup_tpl : public _heap_cleanup_helper
{
public:
_heap_cleanup_tpl(p_alloc_type **p_heap_block) :
_heap_cleanup_helper((void **)p_heap_block)
{
}
};
The user-defined new-operator is as follows:
void *operator new (size_t p_cbytes)
{
void *l_retval = malloc(p_cbytes);
if (
l_retval != NULL &&
*_heap_cleanup_helper::m_last->m_heap_block == NULL &&
_heap_cleanup_helper::m_last->m_guard_block == NULL
)
{
_heap_cleanup_helper::m_last->m_guard_block = l_retval;
}
if (p_cbytes != 0 && l_retval == NULL) throw std::bad_alloc();
return l_retval;
}
void operator delete(void *p_buffer)
{
if (p_buffer != NULL) free(p_buffer);
}
I think it's kind of wierd for a constructor to raise an exception.
Could you have a return value and test it in your main?
class Blah
{
public:
Blah()
{
if Error
{
this.Error = "oops";
}
}
};
void main()
{
Blah* b = NULL;
b = new Blah();
if (b.Error == "oops")
{
delete (b);
b = NULL;
}