在 C 和 C++ 中 assert 是一个 非常 重量级例程,将错误写入 stdout 并终止程序。在我们的应用程序中,我们实现了更强大的断言替代品,并为其提供了自己的宏。已尽一切努力更换 assert 用我们的宏,但是还有很多方法 assert 可以重新引入(例如,从内部第三方库、简单注入等)

关于我们如何减少、限制甚至消除使用的任何建议 assert?最好的答案将是编译器可以为我们捕获的答案,这样我们就不必像现在一样照顾代码库。

有帮助吗?

解决方案

我不知道我真正了解的问题,其实。断言只有当他们去了,这是很好的,无论如何,因为你在一个异常情况现在已经贵。

assert时,才会启用在调试版本,所以要使用第三方库的发布版本。但实际上,断言不应该去关闭每一刻。

其他提示

它可以很方便在内置的断言设施改善(提供堆栈跟踪,核心转储,谁知道)。在这种情况下,如果你有让你的开发人员跟着你有什么标准(如“而不是assert()使用SUPER_ASSERT()”或其他),你可以把自己的assert.h头中包含路径提前编译器的运行目录的问题的头。

这将几乎保证使用标准assert()宏人会得到一个编译错误或让你的断言功能(这取决于你有你的assert.h头做的)。

这将取决于(至少部分地)对你改变什么。假设你不介意它打印出正常的消息,主要是想摆脱它调用abort()的,你可以考虑只留下assert(),而是定义自己的abort()版本。

在理论上,这样做是不可移植的 - 但在现实中,abort()是在标准库中一个相当正常的功能,如果你连接你自己的,而不是,你得到它的行为。有时(特别是一些微软的接头),你必须做一些工作,以获得链接与你替换他们abort()合作,但它很少会非常困难。

我认为你的问题是完全正确的。如果您已经实现了自己的错误处理,您可能需要:

  1. 即使在发布版本中也始终触发断言。
  2. 在断言触发时实现更好的错误报告。您可能想要发送错误报告或写入日志文件。

话虽这么说,我没有看到任何始终有效的解决方案。

  • 如果幸运的话,第三方库使用 ASSERT 宏,您可以自己重新定义,只要定义此宏的文件具有某种类型 #pragma once 或者 #ifndef __HEADERFILE_H__ #define __HEADERFILE_H__ 防止多重包含的规定。单独包含头文件,重新定义 ASSERT 就可以了。

  • 如果它们直接包含assert.h或cassert,我猜你只能修补代码。进行最少的代码更改,将更改保存为补丁文件,并在更新库时希望补丁仍然有效。将补丁添加到版本控制中。

如果这不起作用,请重新考虑问题是否确实需要第三方库中的内部断言。仅发布版本,这会消除断言,并添加断言来检查代码内的正确性。检查返回值的有效性。如果触发了这样的 ASSERT,您仍然可以深入研究第三方代码以查看导致问题的原因。

我想问题是有效的。

我自己的断言扩展到ASM如果触发(“INT3”),这相当于一个断点。我还发现得多有用用于调试比简单的终止。

我简单地将其称为“ASSERT()”,而不是正常的“断言()”,并在所有避免使用断言()的

最明显的做法似乎是给自己的主张了自己的名字,从assert()略有不同的版本。然后,你可以搜索文本,看连接信息等,针对文本字符串“_assert”你知道你有一个问题,当你看到它。

在我自己的代码,我总是使用Assert(),扩展到自己的功能执行的断言,或扩展到((void)0)用于发布版本。编译器将会把((void)0)表达到什么,但它仍然被作为一种表达。因此

Assert(3 == x);

将变成

((void)0);

和分号具有去处。

顺便说一句,我曾经在一个GUI应用程序,其中断言是一个特殊的GUI模式弹出对话框。你有三个选择:忽略,忽略永远,或断裂。忽略将忽略断言,并继续运行。忽略永远会设置一个标志,直到你在调试器重新启动程序,即断言不会再开火。断裂将允许断言打入调试器。

我不记得他们是如何保证每个断言有自己的旗帜。也许当你写的断言()调用,您必须指定一个唯一的整数?这将是很好,如果是比这更加自动化。我敢肯定,实际implmentation是位向量,一下子就定了位,当你选择了忽略,直到永远。

您似乎缺少一个事实,即第三方代码的“标准” assert行为的假设下,最有可能写的。即该代码期望程序终止失败的断言。通常如下断言的代码不能,也不会正确断言的情况被打破工作。 99例出的100不会在所有的工作。 99例选自100它将简单地崩溃,即该程序将反正终止。

要相信,通过重写第三方代码的assert行为,你会以某种方式使程序更长寿是幼稚的最好的。

如果源代码是您的控制之下:

#define NDEBUG
// Before
#include <assert.h>
// Or other header that includes assert.h

或者使用预编译的头或编译选项来定义NDEBUG

有关第三部分二进制文件,使用它们的发布版本。

在图书馆查找头assert(假设他们是你的文件系统上的实际文件),并与一个无效的东西代替它

// #define assert(condition) ... /* old definition */
#define assert(condition) ((condition) & "PLEASE DO NOT USE ASSERT" = 42)
scroll top