一个隐含的try {}抓住了main

时间:2015-12-08 19:52:58

标签: c++ linux c++11

在我的每个主要功能中,我想捕获某些类别的异常并将它们转换为退出代码。

是否有更优雅的解决方案,比使用宏来开始和结束每个主要功能,将粘贴我想要的隐式try {} catch

我可以通过std::set_terminate功能以某种方式实现这一目标吗?

示例:

int main(){
    try { //<- insert this

    /*
    the business logic goes here
    */

    //-> and insert this
    }
    catch(const Someclass1& e){ return 2; }
    catch(const Someclass2& e){ return 3; }
    //...
    catch(...){ return 1; } 
}

6 个答案:

答案 0 :(得分:6)

A clean way涉及使用翻译函数和所有异常样板,它返回相应异常的退出值。

template <typename Callable>
int call_and_translate_for_boundary(Callable&& func)
try {
    func();
    return 0;
}
catch(const Someclass1& e){ return 2; }
catch(const Someclass2& e){ return 3; }
//...
catch(...){ return 1; } 

在您自己的代码中,您只关心自己使用lambda包装业务逻辑并将其传递给翻译函数,以便它可以为您捕获和翻译。

int main() {
    return call_and_translate_for_boundary([&]{
        //business logic here
    });
}

答案 1 :(得分:1)

如果你愿意,我猜你可以用宏做某事。以下是:

#define MY_MAIN int main(int argc, char** argv) try // <- yes, try here
#define MY_CATCH catch (const Someclass1& e){ return 1; } \
                 catch (const Someclass2& e){ return 1; } \
                 ... \
                 catch (...) { return -1; }

MY_MAIN
{
    // usual business...
    return 0;
}
MY_CATCH

这个想法是让宏写一个尝试捕捉&#34;围绕&#34;主要功能体,这都是合法的。

int main() try { throw 1; } catch (int i) { return 0; }

little example live

答案 2 :(得分:1)

我通常这样做:

int main2();

int main() try {
    return main2();
} catch(std::exception &e)
{ 
    // some display...
}

当然,您可以拥有更多捕获处理程序。

如果您需要在多个入口点放置相同的捕获处理程序列表,那将是一个不同的问题。解决方案是catch(...) { foo(); },其中foo()函数try { throw; }后跟所有捕获处理程序。

答案 3 :(得分:0)

我对此表示怀疑。在调用终止时,您已经丢失了所有异常信息(更准确地说,您从未使用过它 - 当没有可用的处理程序且在呼叫站点进行确定时调用终止)。当没有适用于此的处理程序时,甚至不会创建异常对象。

答案 4 :(得分:0)

我熟悉的cleanest solution看起来像:

void standard_exception_handler();

try {
    whatever();
}
catch (...)
{
    standard_exception_handler();
}

void standard_exception_handler()
{
    try {
        throw;  // a bare throw preserves the original exception information
    }
    catch (const std::exception& ex)
    {
        ...
    }
    catch (const other_exception& ex)
    {
        ...
    }
}

要在公共处理程序之外使用处理程序,您需要让公共处理程序对已知类型进行操作(例如,将catch (...)更改为catch (const my_exception& ex),并在公共处理程序内进行必要的更改) ,或使用嵌套的try块:

try {
    try {
        whatever();
    }
    catch (...)
    {
        standard_exception_handler();
    }
}
catch (const who_knows& ex)
{
    // log and exit
}

答案 5 :(得分:0)

我可能会改进它,但我发现我可以

有了这个,我的main s不必“知道”这个异常到exitcode的翻译,这是我的目标:

#include <stdexcept>
#include <cstdlib>

struct Someclass1 {};
struct Someclass2 {};

bool hasDefaultExceptionHandler = (std::set_terminate([](){
    try { throw; }
    catch(const Someclass1& e){ exit(2); }
    catch(const Someclass2& e){ exit(3); }
    catch(...){ exit(1); } 
}), true);

// Main has no idea
int main(){
  throw Someclass2{};
} //will exit with 3

感谢大家的好主意。