如何断言()而不使用abort()? [英] How can I assert() without using abort()?

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

问题描述

如果我使用 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()feature。幸运的是,这是非常简单的。

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.

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 b
$ b

main.cc

#include<iostream>

struct Wrong { };

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

    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的C ++编程语言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()?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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