In my project I found a piece of code in which a method was getting called in constructor's initializer list.
Test2(Test* pTest):m_pTest(pTest), m_nDuplicateID(pTest->getTestID())
{
}
I observed that there is a chance that the users of Test2 might pass NULL to the constructor. Since the pointer is used without validation there are chances of Access Violation.
This triggered me to look into exception handling in constructor's initializers list. I found in one of the article that try can be used inside initializer list. I wrote small test program to test this concept:
//Test class stores the unique ID and returns the same with API getTestID
class Test
{
public:
Test(int nID):m_nID(nID){
}
int getTestID() const
{
return m_nID;
}
private:
int m_nID;
};
class Test2
{
public:
Test2(Test* pTest)
try :m_pTest(pTest), m_nDuplicateID(pTest->getTestID())
{
}
catch (...)
{
cout<<"exception cought "<< endl;
}
void printDupID()
{
cout<<"Duplicate ID" << m_nDuplicateID << endl;
}
private:
Test* m_pTest;
int m_nDuplicateID;
};
int main(int argc, char* argv[])
{
Test* pTest = new Test(10);
Test2 aTest2(pTest);
aTest2.printDupID();
delete pTest;
return 0;
}
This code is not getting compiled in VC6.0. Do I need to make any changes to make it compile in VC 6.0?
Also, in one of the article I found that using try in constructor's initializer list does not strictly confirms to C++ standards. In that case, how do we handle the exceptions in constructor's initializers list (standard way of handling )?
Thanks.
C++ Standard Section 15 / 3
A function-try-block associates a
handler-seqwith thector-initializer,
if present, and the function-body. An
exception thrown during the execution
of the initializer expressions in the
ctor-initializer or during the
execution of the function-body
transfers control to a handler in a
function-try-block in the same way as
an exception thrown during the
execution of a try-block transfers
control to other handlers.
class C
{
int i;
double d;
public:
C(int, double);
};
C::C(int ii, double id)
try : i(f(ii)), d(id)
{
//constructor function body
} catch (...)
{
//handles exceptions thrown from the ctor-initializer
//and from the constructor functionbody
}
Firstly, if you dereference the NULL pointer standard C++ does not guarantee that that an exception will be thrown, so your code is useless for this case.
Secondly, if an exception were thrown, what would your exception handler do?
Thirdly, constructor/function exception blocks are widely considered to be awaste of time - take a look at this http://www.gotw.ca/gotw/066.htm and other articles on Herb Sutter's GotW site.
According to this article, it looks like you just can't do that in VC++ 6.0
You'd either have to upgade to 7.0 or just do the initialization in the constructor body instead.
Can't you just use a function to check the ptr, e.g.:
template<typename P>
P* checkPtr (P* p)
{
if (p == 0)
throw std::runtime_error ("Null pointer");
return p;
}
class Test2
{
public:
Test2 (Test* pTest)
: m_pTest (checkPtr (pTest))
{
}
Test* m_pTest;
};
People still use VC6?
Seriously, VC6 is hardly a standards-complaint compiler. Do yourself a favor and at least get VS2005. VC6 is your problem.
Try VS2008 express and see if it compiles.
The other option, of course, is to take a reference on construction, which needs to be bound.
(for fellow googlers)
Another solution if we don't want to store a copy of the ptr / shared_ptr :
class Foo::Pimpl
{
public:
bool paramTest_;
Pimpl(ConstNodePtr root)
try :
paramTest_( root ? true : throw std::invalid_argument("Foo (pimpl) constructed from NULL node")),
...
{
...
} catch (...)
{
throw; // rethrow
}
There are many useful answers already, but I'll try to add a little bit, maybe it will help someone.
First of all, as others already mentioned - dereferencing a nullptr or invalid pointer (address) doesn't throw an exception in the standard C++. MSVC supports it through its Structured Exception Handling, but it's not portable. Read more about it in this answer.
The function try block in a constructor doesn't allow you to suppress the exception, it will propagate anyway if you don't throw another one. And when you enter the catch clause, all members of the class are already destroyed. So the only plausible thing you can do in it is to log the error somehow or maybe change some global variables. That's why it's considered more or less useless.
As for your initial code
Test2(Test* pTest):m_pTest(pTest), m_nDuplicateID(pTest->getTestID())
{
}
you could use the ternary operator to check for pTest's nullness just in the initializer list and do some appropriate actions in case it is null - just set m_nDuplicateID to nullptr or some other value depending on its type, call another function and use it return type, etc:
Test2(Test* pTest):
m_pTest(pTest),
m_nDuplicateID( pTest ? pTest->getTestID() : /*some value or call*/ )
{
}
you could even use several nested ternary operators to create more complicated execution flows.
And just for completeness, it's not the case with your code, but it may worn someone in the same situation. If you used your class's member m_pTest to initialize m_nDuplicateID, that would depend on the order of these members in class's declaration, because class members in the initializer list get initialized in the order of declaration and not in the order they appear in the initializer list itself, so it can be a problem and it's better to avoid members initialization order dependencies:
class A
{
A( B* pTest );
int m_nDuplicateID;
B* m_pTest;
};
A::A( B* pTest ) :
m_pTest( pTest ),
m_nDuplicateID( m_pTest->someMethod() ) // here m_pTest isn't initialized yet,
// so access violation probably
{
}
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.
While reading about the Drop trait, I found a lot of similarities between the drop method of Rust and the destructor in a C++. What is the difference between the two?
In practice, there is no appreciable difference. Both are used to clean up the resources of a type when appropriate.
Resources will be cleaned up irrespective of implementation of the Drop trait, won't they?
Yes. The compiler essentially automatically implements Drop for any type where the programmer does not. This automatic implementation simply calls drop for each member variable in turn.
If you allocate a resource that Rust doesn't know about, such as allocating memory directly from an allocator, Rust won't know that the returned value needs to be dropped or how to do so. That's when you implement Drop directly.
See also:
Running Code on Cleanup with the Drop Trait
The only differences I know of are related to features that C++ has but Rust doesn't. Other folks have mentioned inheritance in the comments above, but a simpler example might be types with multiple constructors. In Rust, depending on what we mean by "constructor", we could say that every type has exactly one constructor (the syntax where you name the type and initialize all its fields). But in C++ a type can have multiple constructors, and importantly, one constructor can delegate to another. Here's a quick example:
class foo {
public:
// the inner constructor
foo(bool throw_in_inner_ctor) {
if (throw_in_inner_ctor) {
throw runtime_error("throw in inner ctor");
}
}
// the outer constructor, which delegates to the inner one
foo(bool throw_in_inner_ctor, bool throw_in_outer_ctor)
: foo(throw_in_inner_ctor) {
if (throw_in_outer_ctor) {
throw runtime_error("throw in outer ctor");
}
}
// the destructor
~foo() {
cout << "foo dtor\n";
}
};
int main() {
try {
cout << "construct a foo that throws in its inner ctor\n";
foo(true, false);
} catch (runtime_error) {}
try {
cout << "construct a foo that throws in its outer ctor\n";
foo(false, true);
} catch (runtime_error) {}
}
This prints:
construct a foo that throws in its inner ctor
construct a foo that throws in its outer ctor
foo dtor
What we're seeing here is that when the inner constructor throws, the destructor of foo doesn't get invoked. But when the outer constructor throws, it does. The rule is that our foo will get destructed if any constructor returns without an exception, regardless of what other delegating constructors might do. Rust has no equivalent to this rule, both because Rust doesn't have delegating constructors, and because constructors in Rust (if you want to call them that) cannot run arbitrary code and cannot fail.
Lets say I have a constructor like so
Something(SomethingElse) noexcept : member{SomethingElse, something_that_might_throw()} {
...
}
Is a noexcept okay in this case if the construction of member can throw? In the above example the member variable member is of a type I do not know.
On a side note: Are there other edge cases one needs to worry about when using noexcept?
#UPDATE:(Based on your edit): The original answer applies to everything within the block-scope of the function (constructors inclusive, including constructor-initialization-list). Why don't you try the code and see. :-)
#Original Answer
Something(SomethingElse) : member{SomethingElse} noexcept {
...
}
Your code would not compile that way. noexcept comes before the colon :
Something(SomethingElse) noexcept : member{SomethingElse} {
...
}
To your question:
Is a noexcept okay in this case if the member class constructor can
throw?
No, it's not okay. The noexcept specifier is a promise that an exception will not leave that function or constructor. Should it leave, the runtime will terminate your program.
If a search for a matching exception handler leaves a function marked
noexcept or noexcept(true), std::terminate is called immediately.
This applies to the constructor.
Despite the try..catch block, the code below gets terminated:
struct Base {
Base(){}
Base(int){ throw int(5); }
};
struct Derived : public Base {
Derived(int a) noexcept : Base(a) {}
};
int main()
{
try{
Derived d(45);
} catch(...) {}
return 0;
}
Output:
terminate called after throwing an instance of 'int'
bash: line 7: 7454 Aborted (core dumped) ./a.out
See it Live on Coliru
But if you remove the noexcept specification, you wouldn't abruptly end your program, exception handling will continue normally. :-).
I'll leave you to think of the consequences if you do this kind of thing in production or even a large code base with many contributors. Do not use noexcept if you are unsure of the exception guarantees of all the statements in your function/constructor block
Yes, a noexcept on a constructor applies to base class/member construction.
If you need to deal with such a case, you probably want to use the little-known (and rarely used) function try block. The syntax looks something like this:
#include <iostream>
class bad_initializer {};
int do_throw() {
throw bad_initializer();
return 1;
}
class something {
int member;
public:
something() noexcept
try : member{do_throw()} // <-- initializer list
{
// ctor body goes here
}
catch(bad_initializer const &) {
std::cerr << "initialization threw\n";
}
};
int main() {
something s;
}
Now, the bad news: since you have a member that wasn't constructed, the catch block really has only a few options. Normal processing can't continue--an exception happened in constructing the object, which means the object can't ever finish construction. By the time you catch the exception, there's nothing you can do about that.
If it weren't noexcept, it could catch the exception, then do some processing (release any resources it did acquire successfully) then either rethrow the exception it caught, or throw a different exception (one that better reflected its inability to be constructed).
In this case, your meaningful choices are even more restricted: you can call terminate directly, or you can throw an exception, which will call terminate indirectly. About all the whole try/catch thing has done in this case is give you a chance to do a little processing before terminate gets called.
In general it's not okay, but in certain circumstances it may be
noexcept is a promise, similar to the const qualifier of member functions, but unlike const it's not enforced at compile time (the compiler will not issue an error and perhaps not even a warning, if a noexcept function may actually throw, but see below). Thus, you can declare a function noexcept even if a compiler-generated check would find that this function may throw and the code will compile (otherwise your question would be impossible).
However, that defeats the purpose of noexcept. The main purpose is to indicate (1) to the programmer that they can use a certain functionality without worrying about exception safety, and (2) to the compiler that it does not need to add code for stack unwinding. Instead, if an exception is thrown in a noexcept function, the run-time will invoke std::terminate(), as required by the standard.
So, in general your constructor should only be noexcept, if all its functionality, including the construction of bases and members is too.
However, there is an exception. If you know that some method will never throw given any input possible in the particular situation, even if it may throw under other circumstances and hence not be noexcept, you can call this method in a noexcept situation. For example,
// requires non-negative x, will throw std::runtime_error for negative x
int my_func(std::int64_t x);
struct my_struct {
std::int64_t q;
my_struct(int x) noexcept : q(std::int64_t(x)*std::int64_t(x)) {}
int member() const noexcept { return my_func(q); } // fine: q>=0
};
In the situation of your post, this means if member(somethingelse_type) is not noexcept, but you know (from conditions outside the code snipped in your post) that no exception will be thrown for the particular argument provided in this circumstance, you may declare Something(SomethingElse) noexcept.
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.
Have a class with couple of integers and a pointer ,
class A {
int a;
int b;
char* s;
public:
...
class ConstructA {
A &a;
public:
ConstructA (A& ta) : a(ta) {}
...
};
};
As seen ConstructA is responsible for constructing object A.
I want to write a method to see if ConstructA was successful in constructing the object a. How would you go about it ?
Since there is no way for a constructor to fail in C++, an object either:
does not exist
is successfully constructed.
If a constructor throws an exception, the object effectively does not exist at the point the exception is caught.
You may want to implement an additional method such as isOK() that returns whether or not the internal state of the object represents something useful. For example, if you have an object that represents a file, then you could use isOK() to indicate that the file could be successfully opened. However, as far as C++ is concerned, the file object would be fully constructed whether or not the file could be opened.
Having said that, I'm not entirely sure what the role of the ConstructA class is in your example.
As a general rule, if there is any failure in construction you will get an exception thrown -- either a program-specific exception from the object itself, or else a memory exception or something similar from the runtime.
In this particular case, you are not constructing an object of type A, you are initializing a reference. So there is no construction that has an opportunity to fail.
(Perhaps a little more detail about what you are trying to accomplish would help somebody give a better answer?)
You're ConstructA is just trying to hold on to a reference of an already constructed A, try changing it to this:
class ConstructA {
A a; // Don't make this a reference
public:
ConstructA (A& ta) : a(ta) {}
...
};
First, your ConstructA class makes no sense at all to me. There really are two cases basically:
The construction of an object fails
The object is left in an defined, but restricted state. Strictly, the construction succeeded, but possibly not the the degree that the caller wished. He can optionally later complete the construction.
1. The construction fails
I'll use your ConstructA in the following code just to make the point of signaling about construction failure:
A a0;
try {
A::ConstructA a1(a0);
} catch(...) {
// fail to construct a1
}
Constructors throw exceptions to signal when their constructions fail. The idea is that if construction of an object fails, then the object is not constructed. In other words, the object does not exist. If you have to initialize a1 in an constructor init list, there is a way too:
struct B {
B() try : a1(a0) {
// other constructor code...
} catch(...) {
// fail to construct either a0 or a1, or constructor
// code threw
}
A a0;
A::ConstructA a1;
};
try {
B b;
} catch(...) {
// fail to construct B
}
First, code in the catch block of the constructor is executed, then the exception is automatically propagated to the code that created the B object, and its catch blocks are considered.
Your class ConstructA's constructor could look like this, for example:
struct ConstructA {
ConstructA(A &a):a(a) {
if(!condition_met) {
throw std::runtime_error("condition_met false");
}
}
A &a;
};
2. The object is in a restricted state
That is exactly the case what you have when you have a file stream object, but which is not connected to a file. If in the constructor you find that the file mentioned doesn't exist, you can still fully construct the stream, but set it in a not-opened state. Some operations could be disallowed then and you can have a isOpen or isValid function that you can use to query the state of the object.
This can be applied to other cases too. Some framework i used has a Color class. Default constructing a color class left it in a invalid state, so that it doesn't compare equal to any valid color:
Color c;
assert(c.isValid() == false);
The same technique is used for a null pointer. It's set to a defined, but restricted state when you assign NULL to it:
int *a = NULL;
assert(a == NULL);
You cannot dereference a null pointer for example.
mkal, I always suggest people not to use exception in C++. It cause more problems that it tries to solve.
To answer your question, to avoid exception in C++, you probably can reduce the work you
want to do in your constructor, and create an init() method instead, that returns the error-code if something goes wrong.
Basically, whatever you do in C++ Constructor, it has to succeed.
Hope that helps.