#include <iostream>
using namespace std;
int main (int argc, char* const argv[]) {
int a = 20;
cout<<"address of a is "<<&a<<endl;
try{
throw a;
}
catch (int& z) {
cout<<"address of z is "<<&z<<endl;
}
return 0;
}
The address of a is not same as that of z. It means reference doesn't work in try catch. If not then why compiler is not generating any error? And what does above code mean?
When you throw an object of any type, the Standard allows compilers to make copy of the object as many times as it wishes. Therefore, in the catch block, you might not get the original object you threw, and instead it can be a different object, which is a copy of the original object, or a copy of the copy of the copy of the original object, or so on.
I guess my comment was not so clear so I write something as answer.
When you throw that exception you throw it by value. It means that it'll be copied (it doesn't matter if it's a primitive type or a copied object). Of course when an object is copied then its memory location changes (it's a new object). Why this? Because exceptions can unroll the stack to find a proper catch block. If you throw something by reference what you may get is garbage (because when a variable goes out of scope it'll be destroyed). I said may because in reality the compiler does not allow to throw a reference and you'll always have a copy.
If your exception object is really big you may consider to allocate the object with new and then throw its pointer. But someone has to deallocate it. Are you ready for the risk? Take a look (as example) at the CException implementation on MFC and its Delete() method (they try to make this easy but I'm not really happy of that).
Maybe you wonder why if you have to throw by value you catch by reference. First because it's how std::exception is designed to be used (try to call the what() method of an exception catched by value). Second because it lets the compiler to perform some optimizations (moreover, even if you do not use std::exception, you won't create useless copies of that object).
Related
I am not able to understand, how following code is right,
class cls
{
//just to create obj
};
int main(int argc, char* argv[])
{
try
{
throw cls();//throwing obj as ref
}
catch(cls &ref)
{
}
return 0;
}
I am throwing cls object as reference, will it not die as it comes out of { } scope?
Because catch block cannot access variables of try.
When you throw an exception, you actually generate a copy of the exception object. It is the copy that is received by the catch block, so it is not out of scope even though the original object is.
throw will copy initialize the object, which is how it is able to catch a reference. That said throwing arbitrary potentially non-complex objects around probably isn't as good as using std::exception
The exception handling mechanism will take the value of the throw expression and copy it into a region of memory it has reserved for the purpose. Thus throwing an exception is always 'by value' and cannot be 'by reference.'
When an exception handler is activated then the catch parameter is initialized with the copy created by the exception handling mechanism: If the parameter is a reference type then it is initialized to reference that copy, if the parameter is not a reference type then it is initialized by copy construction.
Given a situation where I want to have a stack allocated object that may throw during construction, but want to handle the exception at the calling site, how do I make the object accessible from outside the try block where it is constructed?
Eg
class MyThrowingClass {
MyThrowingClass() {throw exception();}
doSomethingImportant() {
//...
}
};
int main() {
//Need to catch the exception:
try {
MyThrowingClass myObj;
} catch() {
//actually handle the error
//...
}
//Also need to use myObj later on
myObj.doSomethingImportant();//but we can't use it here because it was scoped to the try block...
}
If I have myObj encased in a try then nothing outside the scope of the try can see it, but I don't want to have everything else inside there because then the code becomes 30 levels of nested try blocks, which is what the exception handling is supposed to remove with using the alternative of init function error codes.
I can't handle the exception inside the constructor as the reaction to the exception depends on the context of the use of MyThrowingClass.
Obviously the problem could be circumvented by having a
MyThrowingClass* pMyObj;
and then being able to wrapper the
pMyObj = new MyThrowingClass();
but surely this should be achievable with a stack allocated object too?
Is the only solution to do something like
MyThrowingClass myObj;
try {
myObj.init();
} catch(...) {
//...
}
at which point we're back to basically as bad as error codes and having an uninitialised or partially initialised object.
Note that this is not intended to be a global object, I want to have something that will be instantiated in many places.
Is it really the ideal solution to have a try block that wraps the entire scope (here everything that would be inside main) and catches that handle every possible exception at the end of that one try block as opposed to being able to handle exceptions vaguely near to their site?
int main() {
try {
//absoultely everything
}
catch (exceptionTypeA &a) {
//...
}
catch exceptionTypeB &b) {
}
}
how do I make the object accessible from outside the try block where it is constructed?
If construction fails, then the object doesn't exist; so there's nothing to access.
surely this should be achievable with a stack allocated object too?
Automatic (i.e. stack-allocated) objects are only initialised once, so even if you handle the exception, there's no way to go back and try to re-initialise it. If you do want to be able to retry, then you'll have to use something more complicated, like the dynamic allocation or two-stage initialisation you propose. Another alternative is something boost::optional (or, from next year, std::optional), which allows you to create and destroy objects at will within a lump of automatic storage.
Is it really the ideal solution to have a try block that wraps the entire scope?
In the typical case, where exceptions aren't handled locally and initialisation failure indicates an unrecoverable error, yes. In your special case, where you can handle it locally and recover, no.
try is designed to scope objects that can throw for a reason. By working around it, you are circumventing that which it's trying to protect you from (using a poorly defined object.) Consider using a function to generate the object. By using a noexcept move constructor, you can guarantee that the move out of the object is safe:
class MyThrowingClass {
public:
MyThrowingClass() {
throw exception();
}
// throw() is *okay* if you don't have noexcept
MyThrowingClass(const MyThrowingClass && other) noexcept {
}
};
MyThrowingClass GetObj() {
try {
return std::move(MyThrowingClass());
} catch(...) {
// return some well defined default or terminate program
}
}
int main() {
MyThrowingClass myObj(std::move(GetObj()));
}
Given a situation where I want to have a stack allocated object that may throw during construction, but want to handle the exception at the calling site, how do I make the object accessible from outside the try block where it is constructed?
Basically, you can't. As for wrapping ALL the code in a try block being a good or bad idea, that depends on the size of "all the code" - a dozen lines or so lines is no big deal.
Do you really want to call MyThrowingClass::doSomethingImportant() if the initialiser throws? Unless you somehow guarantee to fix the broken initialisation in the catch you're then calling methods on a partially initialised object.
Including the call to doSomethingImportant() in the same try block as the construction of the object would give you exactly what exceptions are designed to do: in the event of a problem skip past the following code (which is dependent on the preceding code) to an error handler.
Is it safe to use unique_ptr?
When I use cout in destructor, sometimes it called more then one time. - so it make copy time-to-time. if it take two copy from one object - data can be lost..
#include <memory>
class MyException
{
std::unique_ptr<Type> data;
MyException();
~MyException() {cout<<"test"<<endl;}
MyException(MyException ex&);
};
int main()
{
try
{
try
{
throw MyException();
}
catch (const MyException& ex)
{
throw;
//or?
throw ex; //will be copied?
}
return 0;
}
catch(const MyException/*& will be missed. will ex be copied?*/ ex)
{
throw; //wich ex will be re-throw, copy or original?
//or?
throw ex; //will be copied?
}
}
Can I be sure, that data will not be lost between re-throws?
And is this good practic to use ptr inside exception to collect error info from different levels?
Also, can MyException.data be lost after:
std::exception_ptr ex = std::current_exception();
std::rethrow_exception(ex);
As you discovered, you should always say throw; when you want to re-throw an exception, not not throw ex;. Indeed, throw ex; will copy (and slice, if ex is a reference to a base class!).
So, always catch by reference, and always re-throw without naming the exception.
With gcc 4.7.3 your example doesn't compile, complaining about a missing copy constructor for MyException. This is in the line where it's first thrown, so throw MyException() itself already wants to make a copy (at least in gcc). See also this stackoverflow question and the C++ FAQ.
To answer your question about whether using pointers in exceptions is good practice, I would generally say no. Unless the data to be piggybacked onto the exception is huge (which would likely be a design problem), a stack allocated data structure should be preferred. Performance shouldn't be the main concern during exception handling anyway, so copying stuff around isn't a real problem.
If you really need a pointer (maybe Type has no copy constructor and you can't change that), using shared_ptr could help you in a pinch, although I feel like that would be an ugly hack. I would probably try and reduce the information passed via the exception to the bare minimum that would help callers identify and handle the problem.
Edit: I found the relevant section in the C++ standard, section 15.1, paragraph 5:
When the thrown object is a class object, the copy/move constructor and the destructor shall be accessible, even if the copy/move operation is elided.
So it's actually not legal C++ to throw an exception object without a copy constructor.
I'm currently working on a C++ project, where dynamic arrays often appear.
I was wondering, what could be the correct way to initialize a dynamic array using the new-operator? A colleague of mine told me that it's a no-no to use new within the constructor, since a constructor is a construct that shouldn't be prone to errors or shouldn't fail at all, respectively. Now let's consider the following example: We have two classes, a more or less complex class State and a class StateContainer, which should be self-explained.
class State {
private:
unsigned smth;
public:
State();
State( unsigned s );
};
class StateContainer {
private:
unsigned long nStates;
State *states;
public:
StateContainer();
StateContainer( unsigned long n );
virtual ~StateContainer();
};
StateContainer::StateContainer() {
nStates = SOME_DEFINE_N_STATES;
states = new State[nStates];
if ( !states ) {
// Error handling
}
}
StateContainer::StateContainer( unsigned long n ) {
nStates = n;
try {
states = new State[nStates]
} catch ( std::bad_alloc &e ) {
// Error handling
}
}
StateContainer::~StateContainer() {
if ( states ) {
delete[] states;
states = 0;
}
}
Now actually, I have two questions:
1.) Is it ok, to call new within a constructor, or is it better to create an extra init()-Method for the State-Array and why?
2.) Whats the best way to check if new succeeded:
if (!ptr) std::cerr << "new failed."
or
try { /*new*/ } catch (std::bad_alloc) { /*handling*/ }
3.) Ok its three questions ;o) Under the hood, new does some sort of
ptr = (Struct *)malloc(N*sizeof(Struct));
And then call the constructor, right?
You should let the std::bad_alloc propagate - there's likely nothing reasonable you could do anyway.
First of all, throwing an exception from the constructor is the only reliable way to signal a problem - if there's no exception it means the object is completely constructed. So catching std::bad_alloc alone will not help against other possible exceptions.
Then what can you do to "handle" it in such a way that the other code is aware and can react appropriately?
Use exceptions right - let them propagate to the site where they can be reasonably handled.
The entire purpose of a constructor is to construct an object. That includes initialization. When the constructor finishes executing, the object should be ready to use. That means the constructor should perform any initialization that is necessary.
What your friend suggests leads to unmaintainable and error-prone code, and goes against every good C++ practice. He is wrong.
As for your dynamic arrays, use std::vector instead. And to initialize it, simply pass a parameter to the constructor:
std::vector<int>(10, 20)
will create a vector of 10 integers, all of them initialized to the value 20.
Not a complete answer, just my 2 cents:
1: I would use new in the constructor, although for dynamic arrays, STL is the way to go.
2: the normal error-handling for new is to raise an exception, so checking the returned pointer is useless.
3: don't forget the new-operator to make the story a little bit more interesting.
Short answer:
No, your friend is wrong. The constructor is where you do allocation + initialization. We even have a term called "Resource Acquisition is Initialization" (RAII)... classes acquire resources as part of their initialization in the constructor and classes free those acquired resources in their destructors.
Long answer:
Consider the following code in a constructor:
member1 = new whatever1[n];
member2 = new whatever2[m];
Now, suppose in the above that the second allocation were to throw an exception, either because the construction of whatever2 failed and threw an exception, or the allocation failed and threw std::bad_alloc. The result is that the memory that you've allocated for whatever1 will have been leaked.
For this reason, it is better to use a container class such as std::vector:
MyClass::MyClass(std::size_t n, std::size_t m) : member1(n), member2(m) {}
// where member1 and member2 are of type std::vector
When using type std::vector, if the second allocation fails, the destructor of the previous std::vector will be invoked, causing the resources to be appropriately released. This is probably what your friend meant when he said you shouldn't be using new (you should be using a container class, instead), in which case he would be mostly correct... although there are smart pointer classes such as boost::shared_ptr which provide you with these same safety guarantees and where you would still need to use new, so he still isn't quite right.
Note that if you have only one object/array that you are allocating, then this is not an issue... which is the way things are in your code... you don't have to worry about leaks due to some other allocation failing. Also, I should add that new will either succeed or throw an exception; it will not return NULL, and so that check is pointless. The only instance where you should catch std::bad_alloc is in the case where you have been forced to do several allocations (you are forbidden from using std::vector), in which case you deallocate the other resources in the handler, but then you rethrow the exception, because you should let it propagate.
Your friend is somewhat right. However, it is common practice to do memory reservations in the Constructor, and deallocations in the Destructor.
The problem with methods that may fail in Constructors is as follows: The constructor has no traditional means of notifying the caller of the problem. The caller expects to get an object instance that is not corrupt in any way.
The solution to this problem is to throw/propagate an exception. The exception will always get through and can be handled by the caller.
If you are looking out for a return type i.e. if the function has to return a status then use the separate function (init()) to allocate memory.
If you check are going to check whether the memory got allocated by checking the NULL condition in all the member functions then allocate memory in the constructor itself.
The exception handling (i.e. try...catch) is a better choice.
Apart from calling the constructor the "this" pointer is also initialized.
I have a case in which I have to read an input file in the C'tor, but sometimes this file doesn't exist.
This object is usually held statically, so its C'tor is called while loading the dll.
I can't catch the exception I throw if the file doesn't exist because it's too early, and my executable crashes in an ugly way.
I know it's bad practice to throw exceptions out of a C'tor, but I can't go on if the file doesn't exist, so I have to.
Is there a way to catch the exception while loading the dll, and if not, is there any better solution for this scenario?
Thanks,
Gal
I assume the static object has the file scope (it is outside any function/class definition). You may consider moving it to an accessor function and accessing it only via that function, like this:
class Object;
Object& getObject()
{
static Object object;
return object;
}
The static instance of Object will be initialized upon the first calling of the getObject() method. If the Object's constructor throws, you can easily catch the exception. Just you need to remember wrapping every call of getObject() into a try/catch block (or suffer from the exception bubbling up the stack chain); that may be a bit inconvenient, but on the other hand you may decide to wrap just the logically "first" call, if you know which one it is in the program logic flow.
Throwing exceptions out of a constructor is not necessarily a bad practice. In fact, RAII usually requires you to do this sort of things, because objects have an internal invariant that must be satisfied, and if the constructor can't initialize the object and leave it in a valid state, then it's the only way to go.
Throwing exceptions from a destructor, on the other hand, is a bad practice (and also a dangerous one). But throwing them from a constructor should be OK.
If you can use c++11 then there is a lambda and unique_ptr<> solution to this:
// In some_file.hpp
#pragma once
#include <memory>
#include <stdexcept>
class CtorThrows {
public:
CtorThrows (int value) {
if (value < 10) {
throw std::runtime_error("oops!");
}
}
};
class ClassWithStatic {
public:
private:
static std::unique_ptr<CtorThrows> bad_member_; // <-- static member
};
and then
// In some_file.cpp
#include "some_file.hpp"
// Create a lambda function to initialize the static member variable.
std::unique_ptr<CtorThrows> ClassWithStatic::bad_member_ = []() {
try {
int value = 5; // in this case, it is a bad value
// This only returns successfully if bad_value DOESN'T cause
// the ctor to throw and exception.
return std::make_unique<CtorThrows>(value);
} catch (std::runtime_error &e) {
std::cerr << "OOPs! Here's a nice error message" << std::endl;
exit(1);
}
return std::unique_ptr<CtorThrows>(nullptr);
}();
Using a unique_ptr lets you do this even with classes with that have a deleted or private copy constructor and copy assignment operator.
Redesign the object in such a way that it opens the file later - for example when the data from the file is requested the first time.
Alternatively replase the static object with a static pointer and call new when needed. It's better to use a smart pointer like auto_ptr.
How about separating reading the input file from the Constructor? You could have a separate Init() Method that must be called after constructing the object but before the object is actually ready to use.
You're right that you can't catch exeptions that happen during the initialization of static objects.
Since you're writing a DLL: Each DLL can have an entry-point, and inside this entry point exception handling works. (It's the same as main in your main-program). I'd remove the static instances of your classes, replace them with pointers and initialize these pointers inside dllmain.
That'll solve your problems once for all.
Btw - the DLL entrypoint gets called on load, unload and other events such as process attach/detach ect. Be sure you use the correct place to initialize your classes.
One way may be to "design" this to make the calling code (i.e. the code outside the dll) responsible for making sure all dependencies of the dll is in place. A function in the calling code that makes sure the dll's dependencies, in this case the file, is in place and is loadable before loading the library. If not, it can gracefully exit.