Hello good folk of StackOverflow.
Is there a better way of dealing with exceptions in the constructor of member variables? I am having to interact with a library class that may or may not throw an exception in it's constructor (cannot be checked ahead of time) and I want to avoid the use of pointers in my class (if there is a crash, I want all destructors to be properly called even if I mess up). I have currently settled on this implementation (included a dummy stub for an example):
class class_I_have_no_control_over{
public:
class_I_have_no_control_over( int someArgument )
{
if( someInternalConditionThatCantBeTestedExternally )
throw anException;
}
class_I_have_no_control_over( )
{ //Does not throw
}
}
class MyClass{
private:
class_I_have_no_control_over memberVariable;
public:
MyClass()
{
try{
class_I_have_no_control_over tempVariable( 24 );
memberVariable = std::move( tempVariable );
}catch(...)
{
class_I_have_no_control_over tempVariable( );
memberVariable = std::move( tempVariable );
}
}
}
The first method I considered is try catch initializer list : i.e.
class MyClass{
private:
OtherClassThatTrowsOnConstruct member;
MyClass()
try:
member()
{//Normal constructor
}
catch(...)
{//Can translate an exception but cant stop it.
}
But that method can only be used to translate exceptions, not stop them (if you don't throw an exception, the run-time will re-throw the original exception).
Some would say to use dynamic allocation (i.e. pointers with new and delete keywords) but as this library handles shared memory between processes, I am a little weary of what would happen to the dynamic memory contents in the event of a crash in one of the applications (ex. destructor never called and another application is waiting for the one that is no longer running never realizing that it is no longer listening).
The first version can be simplified somewhat, without changing its behaviour:
MyClass() try {
memberVariable = class_I_have_no_control_over(24); // move from temporary
} catch (...) {
// no need to do anything; memberVariable is already default-constructed
// Unless the class is so evil that move-assignment might fail and leave
// the target in a messed-up state. In which case you probably want
memberVariable = class_I_have_no_control_over();
// If that fails, you should probably give up and let the exception go.
}
Unless you have further constraints (such as the class not being movable), this is the best way to deal with your situation. If it were unmovable, then dynamic allocation is probably a reasonable option; use a smart pointer, probably std::unique_ptr, to make sure it's destroyed along with the MyClass object.
#include <memory>
class MyClass{
private:
std::unique_ptr<unmovable_evil> memberVariable;
public:
MyClass() try {
memberVariable.reset(new unmovable_evil(24));
} catch(...) {
memberVariable.reset(new unmovable_evil);
}
};
You might also consider boost::optional as a not-quite-standard alternative to dynamic allocation.
Related
I have been thinking for some time now about this question, but I have not found an answer online satisfactory enough, yet. So here I am.
Assumptions
For the sake of clarity let us restrict ourselves to C++11 and a custom object. By custom object, I mean a user-defined class that the developer has full control of. All the code snippets below are not meant to be compilable or even syntactically correct. They just illustrate a concept.
Boundary conditions
Our object has a nontrivial constructor that can throw exceptions if an error is encountered. When constructing this object I would like to catch and deal with the exceptions as close as possible to the object creation point, to make the code more readable and catching only the constructor exceptions and nothing else.
Example 1
This example is not ideal because this is exactly what I am trying to avoid: dealing with constructor exceptions far away from the constructor.
class MyClass {
public:
MyClass() {
throw 1;
}
}
int main() {
try {
MyClass my_obj;
try {
// Do something with my_obj that may throw
} catch (...) {
// deal with exceptions
}
} catch(...) {
// deal with constructor exceptions
}
}
Example 2
Here I use a std::unique_ptr to separate the object declaration and initialization. The downside is that I now create the object on the heap instead of the stack even if I have no strong reason to do that.
class MyClass {
public:
MyClass() {
throw 1;
}
}
int main() {
std::unique_ptr<MyClass> my_obj_ptr;
try {
my_obj_ptr = boost::make_unique<MyClass>();
} catch (...) {
// deal with constructor exceptions
}
// continue to use my_obj
}
Example 3
Modify the object internal state and check that.
class MyClass {
private:
good_internal_state;
public:
MyClass() : good_internal_state(true) {
try {
throw 1;
} catch(...) {
good_internal_state = false;
}
}
bool IsInternalStateGood() {
return good_internal_state;
}
}
int main() {
MyClass my_obj;
if (!my_obj.IsInternalStateGood()) {
// Do something
}
// continue to use my_obj
}
Right now I am leaning towards the Example 2 case but I would like to know what is the most syntactically correct way to accomplish what I want.
I wouldn't say any of those versions is more or less correct (except for some typos). Example 2 looked like the one I would use. Here scoping seems to be the largest problem. The variable needs to declared outside of the try but must be initialized inside. If you don't like to use the heap std::optional could be usefull:
int main() {
std::optional<MyClass> maybeMyClass;
try {
maybeMyClass.emplace(/*constructor parameters*/);
} catch (...) {
// deal with constructor exceptions
}
// continue to use my_obj
maybeMyClass->foo();
}
Allthough the syntax could imply otherwise, the value managed by std::optional is allocated as the footprint of this std::optional (on the stack in this case).
You could also use a factory function createMyClass that would return a std::optional, this would require MyClass to have a move constructor, which shouldn't be to expensive.
I just want to make sure that i understood the reference correctly.
I got a class A that contains that sets the unique pointer within it's constructor
class CDebug
{
//....
public:
~CDebug();
}
class A
{
public:
A()
{
pDebug = unique_ptr<CDebug>(new CDebug());
if(nullptr == pDebug)
{
CException ex("Nullpointer", __FILE__,__LINE__);
throw ex;
}
}
private:
unique_ptr<CDebug> pDebug;
}
Now when an instance of A leaves it scope:
Delete Operator is called automatically on the unique Pointer object
to free the heap
This forces the Destructor ~CDebug() to run
Now am I right or do i get any memory leaks here?
To answer your question: no, memory will not be leaked. Whenever object A goes out of scope, the destructor will be called, where destructor for CDebug will be called and memory freed.
But as I am very happy when people want to learn how to use unique_ptr, I wanted to point out two things with the code.
Firstly, the nullptr check in the constructor for A is redundant.
A()
{
pDebug = unique_ptr<CDebug>(new CDebug()); //throws at bad allocation
if(nullptr == pDebug) // will never be true
{
CException ex("Nullpointer", __FILE__,__LINE__);
throw ex;
}
}
, pDebug will never be nullptr. If allocation with new fails, std::bad_alloc will be thrown. Unless, of course, you are working with a compiler that does not support exception handling.
Secondly - assuming you have a C++14-compiler - avoid using new. Create a unique_ptr by calling std::make_unique(). Not only does it have the advantage that new/delete are removed from code, but it is also exception safe (see https://herbsutter.com/2013/05/29/gotw-89-solution-smart-pointers/).
A()
{
pDebug = std::make_unique<CDebug>();
[...]
}
Also, if you do not absolutely have to throw a custom exception in the code, put the construction in the initializer list.
A() : pDebug(std::make_unique<CDebug>()) {}
Consider the following class:
struct S { ~S() = delete; };
Shortly and for the purpose of the question: I cannot create instances of S like S s{}; for I could not destroy them.
As mentioned in the comments, I can still create an instance by doing S *s = new S;, but I cannot delete it as well.
Therefore, the only use I can see for a deleted destructor is something like this:
struct S {
~S() = delete;
static void f() { }
};
int main() {
S::f();
}
That is, define a class that exposes only a bunch of static functions and forbid any attempt to create an instance of that class.
What are the other uses (if any) of a deleted destructor?
If you have an object which should never, ever be deleted or stored on the stack (automatic storage), or stored as part of another object, =delete will prevent all of these.
struct Handle {
~Handle()=delete;
};
struct Data {
std::array<char,1024> buffer;
};
struct Bundle: Handle {
Data data;
};
using bundle_storage = std::aligned_storage_t<sizeof(Bundle), alignof(Bundle)>;
std::size_t bundle_count = 0;
std::array< bundle_storage, 1000 > global_bundles;
Handle* get_bundle() {
return new ((void*)global_bundles[bundle_count++]) Bundle();
}
void return_bundle( Handle* h ) {
Assert( h == (void*)global_bundles[bundle_count-1] );
--bundle_count;
}
char get_char( Handle const* h, std::size_t i ) {
return static_cast<Bundle*>(h).data[i];
}
void set_char( Handle const* h, std::size_t i, char c ) {
static_cast<Bundle*>(h).data[i] = c;
}
Here we have opaque Handles which may not be declared on the stack nor dynamically allocated. We have a system to get them from a known array.
I believe nothing above is undefined behavior; failing to destroy a Bundle is acceptable, as is creating a new one in its place.
And the interface doesn't have to expose how Bundle works. Just an opaque Handle.
Now this technique can be useful if other parts of the code need to know that all Handles are in that specific buffer, or their lifetime is tracked in specific ways. Possibly this could also be handled with private constructors and friend factory functions.
one scenario could be the prevention of wrong deallocation:
#include <stdlib.h>
struct S {
~S() = delete;
};
int main() {
S* obj= (S*) malloc(sizeof(S));
// correct
free(obj);
// error
delete obj;
return 0;
}
this is very rudimentary, but applies to any special allocation/deallocation-process (e.g. a factory)
a more 'c++'-style example
struct data {
//...
};
struct data_protected {
~data_protected() = delete;
data d;
};
struct data_factory {
~data_factory() {
for (data* d : data_container) {
// this is safe, because no one can call 'delete' on d
delete d;
}
}
data_protected* createData() {
data* d = new data();
data_container.push_back(d);
return (data_protected*)d;
}
std::vector<data*> data_container;
};
Why mark a destructor as delete?
To prevent the destructor from being invoked, of course ;)
What are the use cases?
I can see at least 3 different uses:
The class should never be instantiated; in this case I would also expect a deleted default constructor.
An instance of this class should be leaked; for example, a logging singleton instance
An instance of this class can only be created and disposed off by a specific mechanism; this could notably occur when using FFI
To illustrate the latter point, imagine a C interface:
struct Handle { /**/ };
Handle* xyz_create();
void xyz_dispose(Handle*);
In C++, you would want to wrap it in a unique_ptr to automate the release, but what if you accidentally write: unique_ptr<Handle>? It's a run-time disaster!
So instead, you can tweak the class definition:
struct Handle { /**/ ~Handle() = delete; };
and then the compiler will choke on unique_ptr<Handle> forcing you to correctly use unique_ptr<Handle, xyz_dispose> instead.
There are two plausible use cases. First (as some comments note) it could be acceptable to dynamically allocate objects, fail to delete them and allow the operating system to clean up at the end of the program.
Alternatively (and even more bizarre) you could allocate a buffer and create an object in it and then delete the buffer to recover the place but never prompt an attempt to call the destructor.
#include <iostream>
struct S {
const char* mx;
const char* getx(){return mx;}
S(const char* px) : mx(px) {}
~S() = delete;
};
int main() {
char *buffer=new char[sizeof(S)];
S *s=new(buffer) S("not deleting this...");//Constructs an object of type S in the buffer.
//Code that uses s...
std::cout<<s->getx()<<std::endl;
delete[] buffer;//release memory without requiring destructor call...
return 0;
}
None of these seems like a good idea except in specialist circumstances. If the automatically created destructor would do nothing (because the destructor of all members is trivial) then the compiler will create a no-effect destructor.
If the automatically created destructor would do something non-trivial you very likely compromise the validity of your program by failing to execute its semantics.
Letting a program leave main() and allowing the environment to 'clean-up' is a valid technique but best avoided unless constraints make it strictly necessary. At best it's a great way to mask genuine memory leaks!
I suspect the feature is present for completeness with the ability to delete other automatically generated members.
I would love to see a real practical use of this capability.
There is the notion of a static class (with no constructors) and so logically requiring no destructor. But such classes are more appropriately implemented as a namespace have no (good) place in modern C++ unless templated.
Creating an instance of an object with new and never deleting it is the safest way to implement a C++ Singleton, because it avoids any and all order-of-destruction issues. A typical example of this problem would be a "Logging" Singleton which is being accessed in the destructor of another Singleton class. Alexandrescu once devoted an entire section in his classical "Modern C++ Design" book on ways to cope with order-of-destruction issues in Singleton implementations.
A deleted destructor is nice to have so that even the Singleton class itself cannot accidentally delete the instance. It also prevents crazy usage like delete &SingletonClass::Instance() (if Instance() returns a reference, as it should; there is no reason for it to return a pointer).
At the end of the day, nothing of this is really noteworthy, though. And of course, you shouldn't use Singletons in the first place anyway.
I have an object that I allocate using placement new. When the object is not needed anymore I use its destructor explicitly, then take care of the memory myself, as described in various sources on the web.
It is not clear to me however if the compiler may generate any additional 'magic in the background' for the destructor call, other than just generating instructions for what's inside the destructor. The actual question is: Would anything prevent me from using 'custom destructors' instead of the regular (~ syntax) destructors in the case of 'placement-new'? Simple class methods that contain all the usual destructor code but may additionally take arguments.
Here is an example:
class FooBar {
FooBar() { ... }
...
void myCustomDestructor(int withArguments) { ... }
...
};
int main() {
...
FooBar* obj = new (someAddress) FooBar();
...
obj->~FooBar(); // <- You're supposed to do this.
obj->myCustomDestructor(5); // <- But can you do this instead?
...
// Then do whatever with the memory at someAddress...
}
Any disadvantages going with custom destructors?
While this is technically be possible, I recommend against it.
Destructors are there for a reason: The compiler takes care of calling the destructors of all base classes. If you use your custom destructor, you need to take care of that yourself (and are likely to forget it somewhere).
Additionally, using a different method than the default destructor will be all but obvious to anyone reading your code.
What advantages do you expect from using a custom destructor? I don't see any.
The "extra magic" is that the object ceases to exist only after the destructor is called. So you can't reuse the memory after calling myCustomDestructor since the object "still exists", well, at least not without undefined behavior.
One solution is to make a private destructor and do something like this:
class FooBar {
public:
FooBar() { ... }
static void destruct(FooBar& foobar, int withArguments) {
foobar.myCustomDestructor(withArguments);
foobar.~FooBar();
}
private:
void myCustomDestructor(int withArguments) { ... }
~FooBar() {}
};
int main() {
...
FooBar* obj = new (someAddress) FooBar();
FooBar::destruct(*obj, 5);
// Then do whatever with the memory at someAddress...
}
This calls both the custom "destructor" and the actual destructor, thus telling the compiler the object now ceases to exist.
No, you can't do that without undefined behavior. I would just do this instead:
void FooBar::prepareForCustomDestruction(int arguments)
{
do_custom_destruction = true;
custom_destructor_arguments = arguments;
}
FooBar::~FooBar()
{
if (do_custom_destruction)
{
// custom destruction
}
else
{
// normal destruction
}
}
Then if you want to simulate calling a custom destructor, just call prepareForCustomDestruction first.
obj->prepareForCustomDestuction(5);
obj->~FooBar();
The following sample (not compiled so I won't vouch for syntax) pulls two resources from resource pools (not allocated with new), then "binds" them together with MyClass for the duration of a certain transaction.
The transaction, implemented here by myFunc, attempts to protect against leakage of these resources by tracking their "ownership". The local resource pointers are cleared when its obvious that instantiation of MyClass was successful. The local catch, as well as the destructor ~MyClass return the resources to their pool (double-frees are protected by teh above mentioned clearing of the local pointers).
Instantiation of MyClass can fail and result in an exception at two steps (1) actual memory allocation, or (2) at the constructor body itself. I do not have a problem with #1, but in the case of #2, if the exception is thrown AFTER m_resA & m_resB were set. Causing both the ~MyClass and the cleanup code of myFunc to assume responsibility for returning these resources to their pools.
Is this a reasonable concern?
Options I have considered, but didn't like:
Smart pointers (like boost's shared_ptr). I didn't see how to apply to a resource pool (aside for wrapping in yet another instance).
Allowing double-free to occur at this level but protecting at the resource pools.
Trying to use the exception type - trying to deduce that if bad_alloc was caught that MyClass did not take ownership. This will require a try-catch in the constructor to make sure that any allocation failures in ABC() ...more code here... wont be confused with failures to allocate MyClass.
Is there a clean, simple solution that I have overlooked?
class SomeExtResourceA;
class SomeExtResourceB;
class MyClass {
private:
// These resources come out of a resource pool not allocated with "new" for each use by MyClass
SomeResourceA* m_resA;
SomeResourceB* m_resB;
public:
MyClass(SomeResourceA* resA, SomeResourceB* resB):
m_resA(resA), m_resB(resB)
{
ABC(); // ... more code here, could throw exceptions
}
~MyClass(){
if(m_resA){
m_resA->Release();
}
if(m_resB){
m_resB->Release();
}
}
};
void myFunc(void)
{
SomeResourceA* resA = NULL;
SomeResourceB* resB = NULL;
MyClass* pMyInst = NULL;
try {
resA = g_pPoolA->Allocate();
resB = g_pPoolB->Allocate();
pMyInst = new MyClass(resA,resB);
resA=NULL; // ''ownership succesfully transfered to pMyInst
resB=NULL; // ''ownership succesfully transfered to pMyInst
// Do some work with pMyInst;
...;
delete pMyInst;
} catch (...) {
// cleanup
// need to check if resA, or resB were allocated prior
// to construction of pMyInst.
if(resA) resA->Release();
if(resB) resB->Release();
delete pMyInst;
throw; // rethrow caught exception
}
}
Here is your chance for a double call to release:
void func()
{
MyClass a(resourceA, resourceB);
MyClass b(a);
}
Whoops.
If you use an RIAA wrapper fro your resources you will be much less likely to make mistakes. Doing it this way is error prone. You are currently missing the copy constructor and assignment operator on MyClass that could potentially lead to a double call to Release() as shown above.
Because of the complexity of handling resource a class should only own one resource. If you have multiple resource delegate their ownership to a class that it dedicated to their ownership and use multiple of these objects in your class.
Edit 1
Lut us make some assumptions:
Resources are shared and counted. You increment the count with Acquire() and decrement the count with Release(). When count reaches zero they are automatically destroyed.
class ReferenceRapper
{
ReferenceBase* ref;
public:
ReferenceWrapper(ReferenceBase* r) : ref (r) {/* Pool set the initial count to 1 */ }
~ReferenceWrapper() { if (ref) { ref->Release();} }
/*
* Copy constructor provides strong exception guarantee (aka transactional guarantee)
* Either the copy works or both objects remain unchanged.
*
* As the assignment operator is implemented using copy/swap it also provides
* the strong exception guarantee.
*/
ReferenceWrapper(ReferenceWrapper& copy)
{
if (copy.ref) {copy.ref->Acquire();}
try
{
if (ref) {ref->Release();}
}
catch(...)
{
if (copy.ref)
{ copy.ref->Release(); // old->Release() threw an exception.
// Must reset copy back to its original state.
}
throw;
}
ref = copy.ref;
}
/*
* Note using the copy and swap idium.
* Note: To enable NRVO optimization we pass by value to make a copy of the RHS.
* rather than doing a manual copy inside the method.
*/
ReferenceWrapper& operator(ReferenceWrapper rhsCopy)
{
this->swap(rhsCopy);
}
void swap(ReferenceWrapper& rhs) throws ()
{
std::swap(ref, rhs.ref);
}
// Add appropriate access methods like operator->()
};
Now that the hard work has been done (managing resources). The real code becomes trivial to write.
class MyClass
{
ReferenceWrapper<SomeResourceA> m_resA;
ReferenceWrapper<SomeResourceB> m_resB;
public:
MyClass(ReferenceWrapper<SomeResourceA>& a, ReferenceWrapper<SomeResourceB>& b)
: m_resA(a)
, m_resB(b)
{
ABC();
}
};
void myFunc(void)
{
ReferenceWrapper<SomeResourceA> resA(g_pPoolA->Allocate());
ReferenceWrapper<SomeResourceB> resB(g_pPoolB->Allocate());
std::auto_ptr<MyClass> pMyInst = new MyClass(resA, resB);
// Do some work with pMyInst;
}
Edit 2 Based on comment below that resources only have one owner:
If we assume a resource has only one owner and is not shared then it becomes trivial:
Drop the Release() method and do all the work in the destructor.
Change the Pool methods so that the construct the pointer into a std::auto_ptr and return the std::auto_ptr.
Code:
class MyClass
{
std::auto_ptr<SomeResourceA> m_resA;
std::auto_ptr<SomeResourceB> m_resB;
public:
MyClass(std::auto_ptr<SomeResourceA>& a, std::auto_ptr<SomeResourceB>& b)
: m_resA(a)
, m_resB(b)
{
ABC();
}
};
void myFunc(void)
{
std::auto_ptr<SomeResourceA> resA(g_pPoolA->Allocate());
std::auto_ptr<SomeResourceB> resB(g_pPoolB->Allocate());
std::auto_ptr<MyClass> pMyInst = new MyClass(resA, resB);
// Do some work with pMyInst;
}
I don't see any leak in this small code.
If the constructor throws exception, then the destructor would not be called, since the object never existed. Hence I don't see double-delete either!
From this article by Herb Sutter :Constructor Exceptions in C++, C#, and Java:
constructor conceptually turns a
suitably sized chunk of raw memory
into an object that obeys its
invariants. An object’s lifetime
doesn’t begin until its constructor
completes successfully. If a
constructor ends by throwing an
exception, that means it never
finished creating the object and
setting up its invariants — and at
the point the exceptional constructor
exits, the object not only doesn’t
exist, but never existed.
A destructor/disposer conceptually
turns an object back into raw memory.
Therefore, just like all other
nonprivate methods,
destructors/disposers assume as a
precondition that “this” object is
actually a valid object and that its
invariants hold. Hence,
destructors/disposers only run on
successfully constructed objects.
I think this should clear your doubts!
Your code is fine. But to make it even better, use some kind of smart-pointer!
Edit: for example you can use shared_ptr:
class SomeExtResourceA;
class SomeExtResourceB;
class MyClass {
private:
// These resources come out of a resource pool not allocated with "new" for each use by MyClass
shared_ptr<SomeResourceA> m_resA;
shared_ptr<SomeResourceB> m_resB;
public:
MyClass(const shared_ptr<SomeResourceA> &resA, const shared_ptr<SomeResourceB> &resB):
m_resA(resA), m_resB(resB)
{
ABC(); // ... more code here, could throw exceptions
}
}
};
void myFunc(void)
{
shared_ptr<SomeResourceA> resA(g_pPoolA->Allocate(), bind(&SomeResourceA::Release, _1));
shared_ptr<SomeResourceB> resB(g_pPoolB->Allocate(), bind(&SomeResourceB::Release, _1));
MyClass pMyInst(resA,resB);
// you can reset them here if you want, but it's not necessery:
resA.reset(), resB.reset();
// use pMyInst
}
I find this solution with RAII much simpler.
Just put if (pMyInst) { ... } around release/delete code in your catch and you are fine.
The classic usage to explicitly take ownership is the std::auto_ptr
Something like this:
std::auto_ptr<SomeResourceA>(g_pPoolA->Allocate()) resA;
std::auto_ptr<SomeResourceB>(g_pPoolB->Allocate()) resB;
pMyInst = new MyClass(resA.release(),resB.release());
You transfer the ownership when you call the constructor.