什么是最好的方式执行论断检查在C++?
-
05-07-2019 - |
题
我的意思是,我需要做什么做有益的断言,在我的代码?
MFC是很容易的,我只是用ASSERT(什么).
什么是非MFC的方式?
编辑: 是否有可能停止主张打破在断言。c而不是比我的文件,该文件称为assert()?
编辑: 之间有什么区别 <assert.h>
& <cassert>
?
接受的答案: 载荷的大回答在这个职位,我希望我能接受一种以上的答复(或者有人会把它们全部)。所以答案得到授予兰(为第一个答复).
解决方案
#include <cassert>
assert(something);
对于编译时检查,Boost的静态断言非常有用:
#include <boost/static_assert.hpp>
BOOST_STATIC_ASSERT(sizeof(int) == 4); // compile fails if ints aren't 32-bit
其他提示
这取决于你是否在寻找工作的东西外面的视觉C++。它还取决于什么类型的断言你是在寻找。
有几种类型的断言:
预处理器
这些断言是完成利用预处理指令#error
预处理器的断言是仅仅评估在预处理阶段,因此是没有用的东西,如模板。执行的时间
这些断言是完成使用assert()
功能定义<cassert>
执行的时间的说法只是评估在运行时间。并作为BoltBait指出,没有编制中,如果NDEBUG
宏观已被定义。静
这些断言是完成,如你所说,通过使用ASSERT()
宏观,但只是如果您使用的是MFC。我不知道的另一种方式来做到静态的说法,是一部分C/C++的标准,但是,提高图书馆提供的另一种方案:static_assert
.
的static_assert
从功能的提高图书馆是什么,是要加入的 C++0x标准.
作为一个额外的警告, assert()
功能兰建议不具有同一行为的MFC ASSERT()
宏。前者是一个执行时间主张,而后是一个静态的断言。
我希望这可以帮助!
断言(通常)仅调试
<!>的问题;断言<!>是它通常在调试二进制文件中,并且一些开发人员使用它们就像代码仍然在生产中一样。
这本身并不邪恶,因为代码应该进行密集测试,因此,产生断言的错误肯定会被发现并被删除。
但有时(大多数情况下?),测试并不像想要的那样密集。我不会谈论一个旧工作,我们必须编码,直到最后一分钟(不要问......有时,经理只是......咳...... )...断言添加到下一分钟将被编译并作为发布二进制文件传递给客户端的断言是什么意思?
断言(某些)现实生活中的应用
在我们的团队中,我们需要一些东西来检测错误,同时还需要其他东西来处理错误。我们可能会在Release Build上使用它。
Assert将仅在调试版本中检测并处理错误。
所以我们添加了一个XXX_ASSERT宏,以及一个XXX_RAISE_ERROR宏。
XXX_ASSERT宏将与ASSERT宏做同样的事情,但它将在Debug和Release中构建。它的行为(写一个日志,打开一个消息框,什么都不做等)可以用.INI文件控制,然后它会中止/退出应用程序。
这被用作:
bool doSomething(MyObject * p)
{
// If p is NULL, then the app will abort/exit
XXX_ASSERT((p != NULL), "Hey ! p is NULL !") ;
// etc.
}
XXX_RAISE_ERROR宏只会<!>“; log <!>”;错误,但不会尝试处理它。这意味着它可以将消息记录在文件中和/或打开带有消息的MessageBox和一个继续按钮,另一个用于启动调试会话(根据.INI文件配置)。这被用作:
bool doSomething(MyObject * p)
{
if(p == NULL)
{
// First, XXX_RAISE_ERROR will alert the user as configured in the INI file
// perhaps even offering to open a debug session
XXX_RAISE_ERROR("Hey ! p is NULL !") ;
// here, you can handle the error as you wish
// Than means allocating p, or throwing an exception, or
// returning false, etc.
// Whereas the XXX_ASSERT could simply crash.
}
// etc.
}
在我们的库中引入一年后,只使用了XXX_RAISE_ERROR。当然,它不能用于应用程序的时间关键部分(我们有一个XXX_RAISE_ERROR_DBG),但在其他地方,它是好的。事实上,人们可以使用任何首选的错误处理,并且可以随意激活,无论是在开发人员计算机上,还是在测试人员上,甚至是用户,都非常有用。
要在第二个<!>中回答问题,请编辑<!>“;:
LT <!>; <!> ASSERT.H GT;是C头
LT <!>;了cassert GT <!>;是C ++标准库头...它通常包括<!> lt; ASSERT.H GT <!>;
要在调用assert的文件内部进行分解,可以使用抛出异常的自定义宏或调用__debugbreak
:
#define MYASSERT(EXPR, MSG) if (!(EXPR)) throw MSG;
或者:
#define MYASSERT(EXPR) if (!(EXPR)) __debugbreak();
基本主张使用情况
#include <cassert>
/* Some code later */
assert( true );
最佳做法的笔记
声称是用来识别 运行的国家,应当是真实的.结果,他们都是编出来的释放方式。
如果你有一个情况下,你想要一个主张总是命中,可以通过虚假的。例如:
switch ( someVal ):
{
case 0:
case 1:
break;
default:
assert( false ); /* should never happen */
}
它还有可能传递一条消息,通过断言:
assert( !"This assert will always hit." );
成熟的基本代码常常延长的断言功能。一些共同的扩展,包括:
- 切换称在每一个模块的基础上进行本地化的测试。
- 创建一个额外的断言宏编制出在大多数调试版本。这是所希望的代码也被称为非常常见(百万次,每次二)不太可能是不正确的。
- 允许用户禁用目前打断言,所有声称在编制单元,或所声称的代码。这个停止是良性的声称,从被触发、创造无法使用的版本。
特定于Microsoft的CRT断言
#include <crtdbg.h>
#include <sstream>
...
// displays nondescript message box when x <= 42
_ASSERT(x > 42);
// displays message box with "x > 42" message when x <= 42
_ASSERTE(x > 42);
// displays message box with computed message "x is ...!" when x <= 42
_ASSERT_EXPR(
x > 42, (std::stringstream() << L"x is " << x << L"!").str().c_str());
有一个名为ModAssert的更高级的开源库,它具有适用于Visual C ++和gcc的断言。可能还有其他编译器,不确定。学习它需要一些时间,但如果你想要不依赖于MFC的良好断言,请看看这些。它位于 http://sourceforge.net/projects/modassert/
使用intellisense在visual studio中打开它(右键单击)
// cassert standard header
#include <yvals.h>
#include <assert.h>
yvals.h是windows的东西。所以,就assert()本身而言,包含它的两种方式是相同的。使用<cxxx>
是一种很好的做法,因为它通常不那么简单(命名空间包装和其他魔术)
这对我来说在来电网站上断了......
这是文章,解释了您不想自己编写此宏的原因。
这是我最近在C ++中使用Assertion工具的迭代: http://pempek.net/articles/2013/11/17/cross-platform-cpp-assertion-library/
这是一个可以轻松添加到项目中的嵌入式2文件库。
回答提问者的第三个问题: 我们使用<!>“cassert <!>”的第一个原因而不是<!> quot; assert.h <!> quot;因为,在C ++的情况下,有一个允许,因为C ++编译器可能不会将函数描述存储在代码文件中,而是存储在dll中或编译器本身中。 第二,可能会对功能进行微小的更改,以便促进C和C ++之间的差异,无论是现在还是将来。因为assert.h是一个C库,所以首选使用<!> quot; cassert <!> quot;而在C ++中。