I've project which the main look like that
Object a;
if (! a.initialize(x, y, z))
return EXIT_FAILURE;
// 100 lines using a
a.finalize();
I trying to change this part of code and using RAII idiome.
So, I delete initialize function and finalize and move the code in the constructor and destructor.
In order to catch initialize() error, I throw an exception in the constructor if something fail.
So now, my code goes like this :
try
{
Object a(x, y, z);
// 100 lines using a
} catch (my_exception&)
{
return EXIT_FAILURE;
}
the think that bother is the 100 lines of code. My try is too long for just one error. And I've multiple object like a.
so before my code was linear :
Object a;
if (! a.initialize(x, y, z))
return EXIT_FAILURE;
Object b;
Object c;
if (!b.initialize() || !c.initialize())
return EXIT_FAILURE;
a.finalize();
Now it looks ugly, difficult to read :
try
{
Object a(x, y, z);
try
{
Object b;
try
{
Object c;
}
catch (my_exception_c&)
{
return EXIT_FAILURE;
}
}
catch (my_exception_b&)
{
return EXIT_FAILURE;
}
} catch (my_exception&)
{
return EXIT_FAILURE;
}
How to do to use RAII and keep a code clear ?
In general, create a try block at the level at which you want to handle the exception. In this case, you just need a top-level block to clean up after any exception:
try {
Object a(x, y, z);
Object b;
Object c;
// code using these
} catch (...) {
// end the program if any exception hasn't been handled
return EXIT_FAILURE;
}
Now it's not "too long for one error"; it's the right length for any error which might occur.
It would be a good idea to restrict yourself to exceptions derived from std::exception; then you could give some potentially useful information in the case that it's not handled:
catch (std::exception const & ex) {
std::cerr << "ERROR: " << ex.what() << std::endl;
return EXIT_FAILURE;
}
You only need one catch like this:
try
{
Object a;
Object b;
//100 lines of code
}
catch(ExeptionA& exa)
{
cerr << "error a" << endl;
}
catch(ExeptionB& exa)
{
cerr << "error B" << endl;
}
catch(...){
cerr << "some other error" << endl;
}
(the '...' literally means '...')
This way, you'll catch all exeptions from ObjectA and ObjectB etc. in the same catch. So if you make a custom exception, it might be good to add some info in there where it came from.
You can always have another function like "IsValid()" that you check after the constructor is called instead of throwing an exception. You keep the benefits of RAII (exception safety, protection against initialization/destruction errors, ...) but you will be able to keep your code in the same format as before.
It's not as clean and safe in terms of C++ good practices, because the user can forget to check if it is valid, but the option is there.
Related
I'm new to C++ (coming from C) and writing a class B that is a member of another class A.
The member B will throw an exception if the parent tries to access data that does not exist from B's container (I throw an invalid_argument exception). The member B has an object that can be thought of like an STL container, so it will be for this example.
My question is: if I catch the original invalid_parameter exception in A, is it considered good C++ practice to re-throw the same exception (I'd re-throw the original error, but I do some logging in it, so the what() is different), or can I just throw std::exception. My code now has many
try { A.calls_b_exception } catch (std::invalid_argument& ie) {...} catch (std::exception& e) {...}
blocks and I was wondering if I could reduce them to
try { A.calls_b_exception } catch (std::exception& e) {...}
and still be following good C++ paradigms.
Example code that is similar to my situation:
class B
{
std::vector<int> stuff;
int get_value(int index)
{
if (index >= stuff.size()) {
stringstream err;
err << "--> invalid index " << index << " for stuff";
throw std::invalid_argument(err.str());
}
}
}
class A
{
B b;
// Assume there are methods to add a bunch of stuff to B
int get_value(int index)
{
try {
b.get_value();
} catch (std::invalid_argument& ie) {
stringstream err;
err << ie.what() << "\n\t--> A::get_value(" << index << ")";
// should I throw the same exception here or is this considered good C++ etiquette?
throw std::exception(err.str());
} catch (std::exception& e) {
throw; // something I was not anticipating handling happened
}
}
}
int main
{
A a;
// Assume more stuff to add to A
try {
a.get_value(-1);
}
catch (std::exception& e) {
stringstream err;
err << "--> invalid index " << index << " for main";
throw std::exception(err.str());exception here?
}
}
You cannot instantiate std::exception(std::string), so my initial approach will not work.
Thanks to those of you who took time to read through my question and help me out.
I am learning c++ at home and I am using the rapidxml lib.
I am using the utils provided with it to open files:
rapidxml::file<char> myfile (&filechars[0]);
I noticed that if filechars is wrong the rapidxml::file throw a runtime_error:
// Open stream
basic_ifstream<Ch> stream(filename, ios::binary);
if (!stream)
throw runtime_error(string("cannot open file ") + filename);
stream.unsetf(ios::skipws);
I think I need to write something like that:
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch ???
{
???
}
I made some googling, but I did not find what I need in the place of the ???.
Could somebody help me?
Thanks!
You need to add an exception declaration next to the catch statement. The type thrown is std::runtime_error.
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch (const runtime_error& error)
{
// your error handling code here
}
If you need to catch multiple, different kinds of exceptions, then you can tack on more than one catch statement:
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch (const runtime_error& error)
{
// your error handling code here
}
catch (const std::out_of_range& another_error)
{
// different error handling code
}
catch (...)
{
// if an exception is thrown that is neither a runtime_error nor
// an out_of_range, then this block will execute
}
try
{
throw std::runtime_error("Hi");
}
catch(std::runtime_error& e)
{
cout << e.what() << "\n";
}
Well, it depends on what you want to do when it happens. This is the minimum:
try
{
rapidxml::file<char> GpxFile (pcharfilename);
}
catch (...)
{
cout << "Got an exception!"
}
If you want to get at the actual exception, then you need to declare a variable to store it in inside the parentheses in place of the three dots.
I have the following code in which dbh constructor may throw exception. The question I have is, dbh is declared inside try block. Will it be available after the catch? If yes, are there any other exceptions where the scope resolution is different than {} ? If not, what is the best design alternative?
status func(const char* field, char** value)
{
try {
dbhandler<recType> dbh(("dbName"),("table"));
}
catch (std::runtime_error &e) {
LOG_ERR << e.what() << endl ;
return false;
}
catch (...) {
LOG_ERR << "Unknown exception" << endl ;
return false;
}
rc = dbh.start("key",field, val);
return rc;
}
Will it be available after the catch?
No. It will be destroyed at the end of the block in which it is declared, just like any other local variable.
try {
dbhandler<recType> dbh(("dbName"),("table"));
} // dbh.~dbhandler<recType>() is called to destroy dbh
What is the best design alternative?
Declare dbh outside of the try block or move all the code that uses it into the try block. Which one makes the most sense depends on your specific use case.
On a somewhat related note, if you catch (...), you should either rethrow the exception or terminate the application: you have no idea what exception is being handled and in general you have no idea whether it is safe to continue executing.
According to your function code, it makes much sense to write it like that:
status func(const char* field, char** value)
{
try {
dbhandler<recType> dbh(("dbName"),("table"));
status rc = dbh.start("key",field, val);
return rc;
}
catch (std::runtime_error &e) {
LOG_ERR << e.what() << endl ;
return false;
}
catch (...) {
LOG_ERR << "Unknown exception" << endl ;
return false;
}
}
This seems to be a trivial question but I got hung on it for a few hours now (maybe too much Java killed my C++ braincells).
I have created a class that has the following constructor (i.e. no default constructor)
VACaptureSource::VACaptureSource( std::string inputType, std::string inputLocation ) {
if( type == "" || location == "" ) {
throw std::invalid_argument("Empty type or location in VACaptureSource()");
}
type = inputType;
location = inputLocation;
// Open the given media source using the appropriate OpenCV function.
if( type.compare("image") ) {
frame = cvLoadImage( location.c_str() );
if( !frame ) {
throw std::runtime_error("error opening file");
}
}
else {
throw std::invalid_argument("Unknown input type in VACaptureSource()");
}
}
When I want to create an instance, I use
// Create input data object
try {
VACaptureSource input = VACaptureSource("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
}
catch( invalid_argument& ia ) {
cerr << "FD Error: " << ia.what() << endl;
usage(argv[0]);
}
catch( runtime_error& re ) {
cerr << "FD Error: " << re.what() << endl;
usage(argv[0]);
}
However, in this case the instance is local to this block and I can't refer to it anywhere else. On the other hand, I can't say
VACAptureSource input;
at the beginning of the program since there's no default constructor.
What is the correct way to do this?
Thanks!
why do you need to refer to it outside the try block?
Instead of
try {
VACaptureSource input = VACaptureSource("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
}
//catch....
//do stuff with input
you could move everything into the try block:
try {
VACaptureSource input = VACaptureSource("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
//do stuff with input
}
//catch....
or you could factor it out into a separate function, which is called from the try block:
void doStuff(VACaptureSource& input){
//do stuff with input
}
try {
VACaptureSource input = VACaptureSource("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
doStuff(input);
}
//catch....
The last one even gives you the nice bonus of separating the construction from use, which places nicely into unit tests where you might want the function to work on a mock object instead.
What about using a pointer (or some RAII version thereof)?
VACaptureSource* input = NULL;
try {
input = new VACaptureSource(...);
} catch(...) {
//error handling
}
//And, of course, at the end of the program
delete input;
A local variable is scoped to the block in which it's allocated (like Java) but it'll destruct as soon as the block ends (unlike Java) so you should either do all the stuff you want in the try block itself (which might not be desirable if you want to only handle constructor exceptions) or you should allocate the object somewhere else (e.g. heap) and use a pointer in the parent block to access it.
Can I just observe that just about any but the most trivial constructor can be expected to throw an exception. You should therefore not consider exceptions to be "special" in some sense, but instead write your code so that it deals with them naturally. This means using RAII, and the other techniques that other answers here have suggested.
You may use a pointer
VACaptureSource* input;
// Create input data object
try {
input = new VACaptureSource("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
}
catch( invalid_argument& ia ) {
cerr << "FD Error: " << ia.what() << endl;
usage(argv[0]);
}
catch( runtime_error& re ) {
cerr << "FD Error: " << re.what() << endl;
usage(argv[0]);
}
And you need to free the object when you finish to use it
delete input
I can't say
VACaptureSource input;
at the beginning of the program since there's no default constructor.
There is a good reason you didn't create a default constructor: namely that a VACaptureSource only makes sense when associated with a file. So don't create a default constructor. Instead simply recognize that the scope of the VACaptureSource object is the try block, and use it inside there.
What about adding a default constructor which leaves the object in a special unconfigured state? Then have an create() function for actually creating it.
Then you can do:
VACaptureSource input;
try
{
input.create("image", "...");
}
catch(...)
{
...
}
Depending on the situation this might be better than messing with pointers. Although then you also have to check if the create() was actually called before doing something...
I don't actually see any probelms here:
A couple of things I would update:
Catch exceptions by const reference.
The compiler may optimize away the copy construction in your code
But it looks neater without it. Just declare input with its parameters.
I would refactor the constructor to take const reference parameters
And I would initialise them in the initialiser list.
Also I would make sure the member 'frame' is actually a smart pointer.
So I would do this (for clarity).
VACaptureSource::VACaptureSource( std::string const& inputType,
std::string const& inputLocation )
:type(inputType)
,location(inputLocation)
{
// Other Code that throws.
}
void playWithCode()
{
// Get input information from user.
VACaptureSource input("image", "/home/cuneyt/workspace/testmedia/face_images/jhumpa_1.jpg");
// use the input object.
// Do not need to play with pointers here.
}
int main()
{
try
{
playWithCode();
}
catch( invalid_argument const& ia )
{ cerr << "FD Error: " << ia.what() << endl;
usage(argv[0]);
}
catch( runtime_error const& re )
{ cerr << "FD Error: " << re.what() << endl;
usage(argv[0]);
}
}
Simple. Don't throw exceptions within a constructor. Not only do you have to wrap the constructor in the try block, you won't be able to handle memory very well in the event you catch an exception (do you call the destructor? how much of the class's memory needs to be deleted?)
UPDATE0: Although, I'm not sure if memory management is a problem if you're using an instance.
UPDATE1: Hmmm, maybe I'm thinking about exceptions in destructors.
int
main2(int argc, char* argv[])
{
MyClass class;
class.doSomething();
}
int
main(int argc, char* argv[])
{
int result = 0;
try {
main2(argc, argv);
} catch (std::exception& se) {
// oh noes!
result = 1;
}
return result;
}
Is there some way to catch exceptions which are otherwise unhandled (including those thrown outside the catch block)?
I'm not really concerned about all the normal cleanup stuff done with exceptions, just that I can catch it, write it to log/notify the user and exit the program, since the exceptions in these casese are generaly fatal, unrecoverable errors.
something like:
global_catch()
{
MessageBox(NULL,L"Fatal Error", L"A fatal error has occured. Sorry for any inconvience", MB_ICONERROR);
exit(-1);
}
global_catch(Exception *except)
{
MessageBox(NULL,L"Fatal Error", except->ToString(), MB_ICONERROR);
exit(-1);
}
This can be used to catch unexpected exceptions.
catch (...)
{
std::cout << "OMG! an unexpected exception has been caught" << std::endl;
}
Without a try catch block, I don't think you can catch exceptions, so structure your program so the exception thowing code is under the control of a try/catch.
Check out std::set_terminate()
Edit: Here's a full-fledged example with exception matching:
#include <iostream>
#include <exception>
#include <stdexcept>
struct FooException: std::runtime_error {
FooException(const std::string& what): std::runtime_error(what) {}
};
int main() {
std::set_terminate([]() {
try {
std::rethrow_exception(std::current_exception());
} catch (const FooException& e) {
std::cerr << "Unhandled FooException: " << e.what() << std::endl;
} catch (const std::exception& e) {
std::cerr << "Unhandled exception: " << e.what() << std::endl;
} catch (...) {
std::cerr << "Unhandled exception of unknown type" << std::endl;
}
std::abort();
});
throw FooException("Bad things have happened.");
// throw std::runtime_error("Bad things have happened.");
// throw 9001;
}
You can use SetUnhandledExceptionFilter on Windows, which will catch all unhandled SEH exceptions.
Generally this will be sufficient for all your problems as IIRC all the C++ exceptions are implemented as SEH.
Without any catch block, you won't catch any exceptions. You can have a catch(...) block in your main() (and its equivalent in each additional thread). In this catch block you can recover the exception details and you can do something about them, like logging and exit.
However, there are also downside about a general catch(...) block: the system finds that the exception has been handled by you, so it does not give any more help. On Unix/Linux, this help would constitute creating a CORE file, which you could load into the debugger and see the original location of the unexcepted exception. If you are handling it with catch(...) this information would be already lost.
On Windows, there are no CORE files, so I would suggest to have the catch(...) block. From that block, you would typically call a function to resurrect the actual exception:
std::string ResurrectException()
try {
throw;
} catch (const std::exception& e) {
return e.what();
} catch (your_custom_exception_type& e) {
return e.ToString();
} catch(...) {
return "Ünknown exception!";
}
}
int main() {
try {
// your code here
} catch(...) {
std::string message = ResurrectException();
std::cerr << "Fatal exception: " << message << "\n";
}
}
Update: This covers c++98 only.
From More Effective C++ by Meyers (pg 76), you could define a function that gets called when a function generates an exception that is not defined by its exception specification.
void convertUnexpected()
{
// You could redefine the exception here into a known exception
// throw UnexpectedException();
// ... or I suppose you could log an error and exit.
}
In your application register the function:
std::set_unexpected( convertUnexpected );
Your function convertUnexpected() will get called if a function generates an exception that is not defined by its exception specification... which means this only works if you are using exception specifications. ;(
Provided that C++11 is available, this approach may be used (see example from: http://en.cppreference.com/w/cpp/error/rethrow_exception):
#include <iostream>
#include <exception>
void onterminate() {
try {
auto unknown = std::current_exception();
if (unknown) {
std::rethrow_exception(unknown);
} else {
std::cerr << "normal termination" << std::endl;
}
} catch (const std::exception& e) { // for proper `std::` exceptions
std::cerr << "unexpected exception: " << e.what() << std::endl;
} catch (...) { // last resort for things like `throw 1;`
std::cerr << "unknown exception" << std::endl;
}
}
int main () {
std::set_terminate(onterminate); // set custom terminate handler
// code which may throw...
return 0;
}
This approach also allows you to customize console output for unhandled exceptions: to have something like this
unexpected exception: wrong input parameters
Aborted
instead of this:
terminate called after throwing an instance of 'std::logic_error'
what(): wrong input parameters
Aborted
This is what I always do in main()
int main()
{
try
{
// Do Work
}
catch(std::exception const& e)
{
Log(e.what());
// If you are feeling mad (not in main) you could rethrow!
}
catch(...)
{
Log("UNKNOWN EXCEPTION");
// If you are feeling mad (not in main) you could rethrow!
}
}
Use catch (...) in all of your exception barriers (not just the main thread). I suggest that you always rethrow (...) and redirect standard output/error to the log file, as you can't do meaningful RTTI on (...). OTOH, compiler like GCC will output a fairly detailed description about the unhandled exception: the type, the value of what() etc.