views:

526

answers:

6

Hi all,

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

+1  A: 

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.

sharptooth
Yes, but then in any getter I have to check if it was initialized, and it's ugly.
Gal Goldman
You can create a openIfNeeded() method which will check and open and call it in each getter. Yeap, it's not awesome and beautiful, but it's not that ugly and it solves your problem.
sharptooth
+1  A: 

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.

Adrian Grigore
As I commented before, I don't want to call the init AFTER the object is ready, be cause then in each getter I have to check if it was initialized already, and it's ugly.
Gal Goldman
In this case (unless I am completely missing the point of your question) you should use the Singleton pattern and let the singleton getter method with intializing the object properly.
Adrian Grigore
+1  A: 

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.

Nils Pipenbrinck
A: 

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.

Fredrik Jansson
+6  A: 

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.

Vlado Klimovský
Shouldn't that be: static Object object; ?
anon
yeah i think so. i'll change it because i would have answered the same way. i hope you don't mind, Vlado? just revert it if so :)
Johannes Schaub - litb
Oh, sure, yes, absolutely ;-). I must have been blind.
Vlado Klimovský
+3  A: 

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.

Marc
Throwing from a constructor is the ONLY way to indicate that the object could not be constructed. Constructors do not provide any other semantic to do it.On the other hand, throwing from a destructor will terminate your program (this might be in the specs; I don't have them with me).
Euro Micelli