如何在不使用 abort() 的情况下 assert()? [英] How can I assert() without using abort()?

查看:70
本文介绍了如何在不使用 abort() 的情况下 assert()?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我使用 assert() 并且断言失败,那么 assert() 将调用 abort(),突然结束正在运行的程序.在我的生产代码中我负担不起.有没有一种方法可以在运行时进行断言,同时能够捕获失败的断言,以便我有机会优雅地处理它们?

If I use assert() and the assertion fails then assert() will call abort(), ending the running program abruptly. I can't afford that in my production code. Is there a way to assert in runtime yet be able to catch failed assertions so I have the chance to handle them gracefully?

推荐答案

是的,事实上有.您需要自己编写自定义断言函数,因为 C++ 的 assert() 正是 C​​ 的 assert(),带有 abort()"功能"捆绑在一起.幸运的是,这非常简单.

Yes, as a matter of fact there is. You will need to write a custom assert function yourself, as C++'s assert() is exactly C's assert(), with the abort() "feature" bundled in. Fortunately, this is surprisingly straightforward.

Assert.hh

template <typename X, typename A>
inline void Assert(A assertion)
{
    if( !assertion ) throw X();
}

如果谓词不成立,上述函数将抛出异常.然后,您将有机会捕获异常.如果你没有捕捉到异常,terminate() 将被调用,这将类似于 abort() 结束程序.

The above function will throw an exception if a predicate doesn't hold. You will then have the chance to catch the exception. If you don't catch the exception, terminate() will be called, which will end the program similarly to abort().

您可能想知道在我们为生产构建时优化断言怎么样.在这种情况下,您可以定义表示您正在为生产而构建的常量,然后在您 Assert() 时引用该常量.

You may wonder what about optimizing away the assertion when we're building for production. In this case, you can define constants that will signify that you're building for production and then refer to the constant when you Assert().

debug.hh

#ifdef NDEBUG
    const bool CHECK_WRONG = false;
#else
    const bool CHECK_WRONG = true;
#endif

main.cc

#include<iostream>

struct Wrong { };

int main()
{
    try {
        Assert<Wrong>(!CHECK_WRONG || 2 + 2 == 5);
        std::cout << "I can go to sleep now.
";
    }
    catch( Wrong e ) {
        std::cerr << "Someone is wrong on the internet!
";
    }

    return 0;
}

如果 CHECK_WRONG 是一个常量,那么对 Assert() 的调用将在生产中被编译掉,即使断言不是一个常量表达式.有一个轻微的缺点,通过参考 CHECK_WRONG 我们输入更多.但是作为交换,我们获得了一个优势,因为我们可以对各种断言组进行分类,并根据我们认为合适的方式启用和禁用它们中的每一个.因此,例如,我们可以定义一组即使在生产代码中也要启用的断言,然后定义一组我们只希望在开发版本中看到的断言.

If CHECK_WRONG is a constant then the call to Assert() will be compiled away in production, even if the assertion is not a constant expression. There is a slight disadvantage in that by referring to CHECK_WRONG we type a little more. But in exchange we gain an advantage in that we can classify various groups of assertions and enable and disable each of them as we see fit. So, for example we could define a group of assertions that we want enabled even in production code, and then define a group of assertions that we only want to see in development builds.

Assert() 函数相当于打字

if( !assertion ) throw X();

但它清楚地表明了程序员的意图:做出断言.使用这种方法,断言也更容易 grep,就像普通的 assert()s.

but it clearly indicates the intent of the programmer: make an assertion. Assertions are also easier to grep for with this approach, just like plain assert()s.

有关此技术的更多详细信息,请参阅 Bjarne Stroustrup 的 The C++ Programming Language 3e,第 24.3.7.2 节.

For more details on this technique see Bjarne Stroustrup's The C++ Programming Language 3e, section 24.3.7.2.

这篇关于如何在不使用 abort() 的情况下 assert()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆