CodeGuru Home VC++ / MFC / C++ .NET / C# Visual Basic VB Forums Developer.com
Results 1 to 12 of 12
  1. #1
    Join Date
    May 2009
    Posts
    19

    'catch' expected - multiple catch blocks needed?

    Using the latest g++, there appears to be a strange quirk in one of my try/catch blocks.

    This refuses to compile:
    Code:
    void Method::run(ScopeContext* context){
    	Variable** paramVars = new Variable*[nParms];
    	ScopeContext* methodContext = new ScopeContext(context->getLevelObjectList(0));
    	try{
    		methodContext->incrementScope();
    		MethodParamSet* paramVals= context->getMethodParams();
    		for(int i=0; i<nParms; ++i){
    			paramVars[i] = new Variable(parms[i].name, paramVals->parms[i]);
    			methodContext->addObject(paramVars[i]);
    		}
    		if(context->getThisObject()!=0){
    			Value* thisObj = context->getThisObject();
    			if(thisObj->type.isClassInstance()){
    				try{
    					ClassInstance* inst = (ClassInstance*) thisObj->ptr;
    					inst->enterScope(methodContext, PRIVATE);
    				}catch(InvalidScopeSetup iss){}
    			}
    			Variable* var = new Variable("this",thisObj);
    			try{
    				methodContext->addObject(var);
    			}catch(InvalidScopeSetup except){
    				throw OperationException("Cannot use this as a parameter to a class-method.");
    			}
    		}
    		ActionChain::run(methodContext);
    	}catch(ReturnValue ret){
    		if((ret.returned==0&&(!this->ret.isPrimitive()||this->ret.getValue().pType!=VOID))
    			||(ret.returned!=0&&ret.returned->type!=this->ret)){
    			throw OperationException("No value returned from a method returning a value, or wrong type returned. Occured " + getAtLineStr());
    		}
    		returned=ret.returned;
    	}
    	delete methodContext;
    	for(int i=0; i<nParms; ++i){
    		delete paramVars[i];
    	}
    	delete[] paramVars;
    }
    But if I add an extra catch block in (at the deepest indentation) there are no errors...
    Code:
    //Surrounding code of the catch block
    if(context->getThisObject()!=0){
    	Value* thisObj = context->getThisObject();
    	if(thisObj->type.isClassInstance()){
    		try{
    			ClassInstance* inst = (ClassInstance*) thisObj->ptr;
    			inst->enterScope(methodContext, PRIVATE);
    		}catch(InvalidScopeSetup iss){
    		
    		}catch(InvalidScopeSetup iss){}//why do I need two?
    	}
    	Variable* var = new Variable("this",thisObj);
    	try{
    		methodContext->addObject(var);
    	}catch(InvalidScopeSetup except){
    		throw OperationException("Cannot use this as a parameter to a class-method.");
    	}
    }
    Any insight? I would've expected the second to give an error, if anything, as I'm catching the same exception twice. I doubt it will affect how my code runs, but it struck me as very odd.

  2. #2
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: 'catch' expected - multiple catch blocks needed?

    Any chance you can give us enough code to compile? If not, what is the error message for the first case?
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  3. #3
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: 'catch' expected - multiple catch blocks needed?

    Looks like that code is written by a Java programmer. Here are a few pointers:
    - Don't use new unless you have to. Dynamic arrays should be replaced by std::vector. Allocating an object and deleting it in the same function makes no sense. Use a local variable instead.
    - Catch exceptions by const reference
    - Don't use C-style casts, prefer to avoid casts altogether, but if you have to use C++-style casts (static_cast, dynamic_cast, reinterpret_cast and const_cast).
    - You seem to be using a lot of exceptions. Prefer to use return values where possible and reserve exceptions for truly exceptional cases.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  4. #4
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: 'catch' expected - multiple catch blocks needed?

    Quote Originally Posted by D_Drmmr View Post
    - You seem to be using a lot of exceptions. Prefer to use return values where possible and reserve exceptions for truly exceptional cases.
    Looks more of a "This can throw so I have to catch it" construct to me (http://www.parashift.com/c++-faq-lit....html#faq-17.7).

    I think the solution is more along the lines of "This threw, but I can't do anything about it. Better let the exception move up so someone higher up can deal it with".

    ...

    I hate return codes.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  5. #5
    Join Date
    Oct 2009
    Posts
    577

    Smile Re: 'catch' expected - multiple catch blocks needed?

    Quote Originally Posted by monarch_dodra View Post
    Looks more of a "This can throw so I have to catch it" construct to me (http://www.parashift.com/c++-faq-lit....html#faq-17.7).

    I think the solution is more along the lines of "This threw, but I can't do anything about it. Better let the exception move up so someone higher up can deal it with".

    ...

    I hate return codes.
    I always wondered why the 'someone higher' should be able to handle a case better than the current function which made the failed call. If so, I would assume the 'someone higher' better had made the call itself.

    I prefer return codes (or better bool returns) over exceptions, and not only cause debuggers weren't able to show the line where an exception was thrown but only where it was handled. I also think that a effective and consequent exception handling only could be made by spoiling the code so that actually the error handling outweights the normal code and make it unreadable cause you never knows where the current exception actually was handled - if at all. I once joined a project where also each positive action was made by throwing exceptions. It was really horrible and the project finally couldn't be maintained properly because of that.

    The main thing when an unexpected error occurs is that the reasons and current environment properly were reported in a way so that the error situation could be fully explained and can be prevented with a further software version. Doing that with exception handling means that every call which could fail must be caught in order to add the environment information of the caller to the exception case. Then it must be thrown again so that the calling function could do the same and so on. I don't think that such a design can be wanted by anyone or that a customer would pay the enormous costs for such a concept. When using return codes or bool returns you can log the call and error hierarchy with trace statements which in the best case can be switched on/off at runtime and actually will allow to report any failed case regardless whether it was successfully handled or not.

  6. #6
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: 'catch' expected - multiple catch blocks needed?

    Quote Originally Posted by monarch_dodra View Post
    Looks more of a "This can throw so I have to catch it" construct to me (http://www.parashift.com/c++-faq-lit....html#faq-17.7).

    I think the solution is more along the lines of "This threw, but I can't do anything about it. Better let the exception move up so someone higher up can deal it with".
    Yes, in several cases an exception is thrown from the catch block.

    My attention was mostly drawn by:
    Code:
    catch(ReturnValue ret)
    That just looks weird. Catching a return value?
    Quote Originally Posted by itsmeandnobodyelse View Post
    I always wondered why the 'someone higher' should be able to handle a case better than the current function which made the failed call. If so, I would assume the 'someone higher' better had made the call itself.
    I don't understand what you are saying here. If I call push_back on a std::vector, how am I supposed to check beforehand if it will throw or not?
    Quote Originally Posted by itsmeandnobodyelse View Post
    I also think that a effective and consequent exception handling only could be made by spoiling the code so that actually the error handling outweights the normal code and make it unreadable cause you never knows where the current exception actually was handled - if at all.
    You don't need to know where an exception will be handled when you throw it. That the whole point of exceptions.
    They can also reduce the amount of error checking code significantly, when used properly. When you use exceptions for just about everything you indeed get horrible code. But that's no reason to avoid exceptions altogether (which is often not even possible, by the way).
    Quote Originally Posted by itsmeandnobodyelse View Post
    The main thing when an unexpected error occurs is that the reasons and current environment properly were reported in a way so that the error situation could be fully explained and can be prevented with a further software version.
    Are you saying that every possible error can always be prevented?
    Quote Originally Posted by itsmeandnobodyelse View Post
    Doing that with exception handling means that every call which could fail must be caught in order to add the environment information of the caller to the exception case. Then it must be thrown again so that the calling function could do the same and so on.
    IMO creating a complete stack trace manually for error reporting is bad design, irrespective of the error handling method. In most cases the required context doesn't involve tracing the entire stack and can be given in a single place. However, that may not be the same place as where you can handle the error. Using exceptions it's easy to pass the context information from the first place to the second.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  7. #7
    Join Date
    Jun 2009
    Location
    France
    Posts
    2,513

    Re: 'catch' expected - multiple catch blocks needed?

    Quote Originally Posted by itsmeandnobodyelse View Post
    I always wondered why the 'someone higher' should be able to handle a case better than the current function which made the failed call. If so, I would assume the 'someone higher' better had made the call itself.
    An example I like to give is that of database transactions. Say you have a service that is responsible for creating a connection to the database. That service will choose which database to connect to, with which privileges, with which user... everything.

    Once you have launched this service and all is well and good, you step into another module, the one that is responsible for actual translation of object into database queries, and then to transform the db answers back into objects. At the very end of this module, is a launch query command.

    Now image this query un-unexpectedly fails, because the database is down. You can't conceivably imagine the launch query function would actually rebuild the connection, with everything from the first service. In particular, that function can't even call the service because it not only has enough information to do so (users etc.), but it can't call the service because of code dependencies.

    So the function throws an exception, which travels up, all the way into the entry point of the service that asked for the transaction. THAT service will then return with a fail code, or fix the connection before trying again, or give up.

    The problem with return codes is that 99% of the time, you end up writing things like this:

    Code:
    ReturnCode my_function()
    {
        ReturnCode code = my_nested_function();
        if(code == FAILED)
            {return FAILED;}
    
        return SUCCESS;
    }
    Is that really any better? You just end up coding the same thing, but doing it manually every step of the way (And the end result is still "Just keep returning the error code until someone higher deals with it"). The worst part of this approach is that even if my_nested_function never fails, you still wrote the code for it!

    In a big project (like the one I'm working on right now), each and every function has a return code. About 50% of our actual code (seriously50%) is checking return codes, but in the end, we never actually ever do anything with them, but just push them up to whoever wants to handle them. We're stuck with them because we have a ton of naked pointers, and manually managed stuff (no RAII), so we can't move to exceptions.

    I don't know if you've ever had the chance to work on large scale projects that use a exception-centric and another that uses return code-centric projects. I have tried both, and I can tell you that the exceptions is not only much more robust (really, exceptions make your app much much safer), it is also several orders of magnitude easier to maintain.

    Finally, exceptions make coding much faster and easier. By having the "some higher up handle it" can mean the difference between writing error handling code for the (literally) thousands of functions/objects/calls, and a single catch clause in "someone higher up".

    My two cents. Cheers.
    Is your question related to IO?
    Read this C++ FAQ article at parashift by Marshall Cline. In particular points 1-6.
    It will explain how to correctly deal with IO, how to validate input, and why you shouldn't count on "while(!in.eof())". And it always makes for excellent reading.

  8. #8
    Join Date
    May 2009
    Posts
    19

    Re: 'catch' expected - multiple catch blocks needed?

    I know its uglyl. I don't like it either, but until all of my code works, I'm not going to change little bits of it that work so the look better (don't fix things that aren't broken) In any case, I am, as was mentioned, mostly a Java programmer, but Java simply can't do what I want to do with this program. But since I am a Java programmer, most of the early code in my C++ projects is ugly, while I adjust to the different conventions and practices. However, I'm not here to fix my conventions and code design..

    What I was wondering is whether there was an obvious reason for why the compiler wanted a second catch block. Seems not, so I'll keep going, and maybe when I do rethink my design, I'll find the problem, since it seems not to be affecting my program right now in any case.

  9. #9
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: 'catch' expected - multiple catch blocks needed?

    Quote Originally Posted by Singing Boyo View Post
    I know its uglyl. I don't like it either, but until all of my code works, I'm not going to change little bits of it that work so the look better (don't fix things that aren't broken) In any case, I am, as was mentioned, mostly a Java programmer, but Java simply can't do what I want to do with this program. But since I am a Java programmer, most of the early code in my C++ projects is ugly, while I adjust to the different conventions and practices. However, I'm not here to fix my conventions and code design..
    It's not about code looking pretty or ugly, it's about whether it works or not. E.g. because you catch by value, your exceptions will be copied. Without seeing the copy c'tor of those classes, we can't tell whether your program will work correctly. And given the fact that you are using new/delete all over the place, chances are they won't.

    What you must understand is that C++ doesn't give you any guarantees about the behavior of a broken program. Many illegal constructs lead to "undefined behavior". That means your program may crash, or it may appear to run just fine. Or it may crash a while later. Consequentially, writing a correct C++ program is as much about writing code in a safe way as it is about testing whether your program works correctly.
    Quote Originally Posted by Singing Boyo View Post
    What I was wondering is whether there was an obvious reason for why the compiler wanted a second catch block. Seems not, so I'll keep going, and maybe when I do rethink my design, I'll find the problem, since it seems not to be affecting my program right now in any case.
    Like monarch_dodra said, it's hard to give any help without some compilable code or at least an error message.
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

  10. #10
    Join Date
    Oct 2009
    Posts
    577

    Smile Re: 'catch' expected - multiple catch blocks needed?

    Quote Originally Posted by monarch_dodra View Post
    An example I like to give is that of database transactions. Say you have a service that is responsible for creating a connection to the database. That service will choose which database to connect to, with which privileges, with which user... everything.

    Once you have launched this service and all is well and good, you step into another module, the one that is responsible for actual translation of object into database queries, and then to transform the db answers back into objects. At the very end of this module, is a launch query command.

    Now image this query un-unexpectedly fails, because the database is down. You can't conceivably imagine the launch query function would actually rebuild the connection, with everything from the first service. In particular, that function can't even call the service because it not only has enough information to do so (users etc.), but it can't call the service because of code dependencies.

    So the function throws an exception, which travels up, all the way into the entry point of the service that asked for the transaction. THAT service will then return with a fail code, or fix the connection before trying again, or give up.

    The problem with return codes is that 99% of the time, you end up writing things like this:

    Code:
    ReturnCode my_function()
    {
        ReturnCode code = my_nested_function();
        if(code == FAILED)
            {return FAILED;}
    
        return SUCCESS;
    }
    Is that really any better? You just end up coding the same thing, but doing it manually every step of the way (And the end result is still "Just keep returning the error code until someone higher deals with it"). The worst part of this approach is that even if my_nested_function never fails, you still wrote the code for it!

    In a big project (like the one I'm working on right now), each and every function has a return code. About 50% of our actual code (seriously50%) is checking return codes, but in the end, we never actually ever do anything with them, but just push them up to whoever wants to handle them. We're stuck with them because we have a ton of naked pointers, and manually managed stuff (no RAII), so we can't move to exceptions.

    I don't know if you've ever had the chance to work on large scale projects that use a exception-centric and another that uses return code-centric projects. I have tried both, and I can tell you that the exceptions is not only much more robust (really, exceptions make your app much much safer), it is also several orders of magnitude easier to maintain.

    Finally, exceptions make coding much faster and easier. By having the "some higher up handle it" can mean the difference between writing error handling code for the (literally) thousands of functions/objects/calls, and a single catch clause in "someone higher up".

    My two cents. Cheers.
    In my experience a suddenly broken database connection is a fatal error where you rarely could recover from. But anyway, if you find exception handling is a worthy concept you may find cases where you could use them sensefully.

    I don't use exception handling if I could avoid it and only those functions have an error code return which realy could fail without handling the error. That normally is the minority of my functions.

    So the scenarios where after each call there is an error return handling is in my opinion a wrong concept as well cause errors that could not handled by the function where them occurred actually are fatal at least for the current operation and hence should be the rare exception. In good projects we would switch-on full tracing in that case and because of the error returns we could trace the whole call hierarchy before finally saying "Sorry, an unrecoverable error has occurred. Please look to your log files".

    Code:
    bool App::execute()
    {
         bool ok = true;
         while (true)
         {
                ok = getwork();
                ok = dowork(ok);
                if (ok == false)
                {
                    usermsg(FATAL, "Sorry we died. Look at " << m_tracefile);
                    return false;
                }   
                if (m_last == quit) 
                   break;     
         }
         return ok;
    }
    
    bool SomeClass::somefunc()
    {
         ...
         if (error_not_handable)
         {
               return errortrace(FATAL_TRACEON, "SomeClass::somefunc: " << " error info: " << info 
                                                                                               << " more info: " << moreinfo);
         }
         return true;
    }
    
    bool OtherClass::otherfunc()
    {
         ...
         if (someclass.somefunc() == false)
               return errortrace(LAST_SEVERITY, "OtherClass::otherfunc: " << " context: " << context); 
          ...
         return true;
    }

  11. #11
    Join Date
    May 2002
    Location
    Lindenhurst, NY
    Posts
    867

    Re: 'catch' expected - multiple catch blocks needed?

    Quote Originally Posted by itsmeandnobodyelse View Post
    In my experience a suddenly broken database connection is a fatal error where you rarely could recover from.
    In my experience, a broken database connection is very recoverable in many cases. For example network communication to database server temporarily down or database server rebooting.

  12. #12
    Join Date
    Jul 2005
    Location
    Netherlands
    Posts
    2,042

    Re: 'catch' expected - multiple catch blocks needed?

    Quote Originally Posted by itsmeandnobodyelse View Post
    So the scenarios where after each call there is an error return handling is in my opinion a wrong concept as well cause errors that could not handled by the function where them occurred actually are fatal at least for the current operation and hence should be the rare exception.
    You should distinguish two meanings of "rare" in this case. There is rare in the sense that it doesn't occur often in a running program and there is rare in the sense that it doesn't happen in many places in the code. An example of the former is memory allocation failure. That won't happen often, but handling this possible error has huge impacts on your code, which can be largely mitigated by using exceptions. E.g. a large amount of functions in the STL can throw a std::bad_alloc. Handling that using return values would be a nightmare.
    Quote Originally Posted by itsmeandnobodyelse View Post
    In good projects we would switch-on full tracing in that case and because of the error returns we could trace the whole call hierarchy before finally saying "Sorry, an unrecoverable error has occurred. Please look to your log files".
    That can be a good approach in some projects, particularly for tailor-made products. For off-the-shelve products it's probably less feasible.

    Your described approach also seems to assume a reproducible error. A broken DB connection typically wouldn't be reproducible (or not easily).
    Cheers, D Drmmr

    Please put [code][/code] tags around your code to preserve indentation and make it more readable.

    As long as man ascribes to himself what is merely a posibility, he will not work for the attainment of it. - P. D. Ouspensky

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  





Click Here to Expand Forum to Full Width

Featured