Code reuse in exception handling

后端 未结 6 1533
无人共我
无人共我 2020-12-08 08:26

I\'m developing a C api for some functionality written in C++ and I want to make sure that no exceptions are propagated out of any of the exported C functions.

The s

相关标签:
6条回答
  • 2020-12-08 08:47

    Jem answer is a little more simpler than this solution. But it is possible to substitute the use of a preprocessor macro with the use of templates. Something like this (more refinements you could made):

    template <class T, void (T::*FUNC)()>
    class CatchWrapper
    {
    public:
    
        static void WrapCall(T* instance)
        {
            try
            {
                (instance->*FUNC)();
            }
            catch (std::bad_alloc&)
            {
                // Do Something 1
            }
            catch (std::exception& e)
            {
                // Do Something 2
            }
            catch (...)
            {
                // Do Something 3
            }
        }
    };
    
    
    class Foo
    {
    public:
        void SomeCall()
        {
            std::cout << "Do Something" << std::endl;
        }
    };
    
    
    int main(int argc, char* argv[])
    {
        Foo i;
        CatchWrapper<Foo, &Foo::SomeCall>::WrapCall(&i);
        return 0;
    }
    
    0 讨论(0)
  • 2020-12-08 08:47

    It would be a shame to loose error information at the language boundary. You really should try to translate all exceptions into an error code usable from C.

    How you do it really depends on what your exception classes look like. If you control your exception class hierarchy, you can ensure that each class provides a translation using a virtual method. If not, you may still find it practical to use a translator function and test the types of the 'std::exception'-derived exception it receives to translate it into an error code, much like Jem suggested (remember: thrown exceptions will hurt performance anyway, so don't worry about the translation being slow).

    0 讨论(0)
  • 2020-12-08 08:51

    You can use only one handler function for all possible exceptions, and call it from each or your API implementation functions, as below:

    int HandleException()
    {
        try 
        {
            throw;
        }
    
        // TODO: add more types of exceptions
    
        catch( std::bad_alloc & ) 
        {
           return ERROR_BAD_ALLOC;
        }
        catch( ... )
        {
            return ERROR_UNHANDLED_EXCEPTION;
        }
    }
    

    And in each exported function:

    try
    {
        ...
    }
    catch( ... )
    {
        return HandleException();
    }
    
    0 讨论(0)
  • 2020-12-08 08:56

    What about:

    try{
        //Your code here
    } catch(std::exception e)
    {
       return translateExceptionToErrorCode(e);
    } catch(...)
    {
       return UNKNOWN_EXCEPTION_THROWN;
    }
    
    0 讨论(0)
  • 2020-12-08 08:59

    Do not ever use catch(...), unless you plan on more or less immediately re-throwing. You will certainly lost any error information you might have had to help you figure out the cause of the error.

    I like your second scheme a little better - catch a known set of exceptions, ideally because they are the only ones your code will throw, and let the rest through - allowing the app to crash is possibly the best thing to do since you have invoked unknown behaviour it is best to "crash responsibly".

    0 讨论(0)
  • 2020-12-08 09:05

    There already is a good answer. But just FYI, its called 'exception-dispatcher' idiom, see C++ FAQ.

    0 讨论(0)
提交回复
热议问题