【问题标题】:Should a library build system turn off asserts by default?库构建系统是否应该默认关闭断言?
【发布时间】:2012-10-16 02:50:07
【问题描述】:

我正在编写一个包含许多断言的库。打开断言后,该库要慢得多,并且该库的全部意义在于它很快,因此断言仅在测试或诊断错误时才有意义。我正在使用 autoconf,要求用户了解这个问题并传递一个标志来配置以禁用断言似乎是标准做法。在这种情况下,只有专家用户知道足以安装适当版本的库!这真的是我应该做的吗?如果是这样,除了“这是专家用户和其他程序员所期望的”之外,还有其他充分的理由吗?

编辑:Here's 一个讨论示例,说明您不应该在发布模式下默认定义 NDEBUG,尽管没有其他理由,因为这样做令人惊讶。

【问题讨论】:

  • 您应该构建两个版本的库,使用断言进行调试和不使用断言优化发布。还可以考虑在发布版本中保留 cheap 断言(如果它们不会影响性能,请测量!)
  • @dribeas 这是个好主意 (stackoverflow.com/questions/11695046/…),尽管至少在 unix 平台上这似乎也是非标准的。如果没有在名称中添加特殊修饰符的库应该是断言库还是非断言库,这仍然存在问题。此外,如果用户不要求两个版本,则默认是否应带有断言。我想说断言应该只存在于请求它们的人,但这似乎与标准做法相反,我想知道为什么会这样。
  • @DavidRodríguez-dribeas 哦等等,我没注意到你说“用断言调试”。这个问题与调试版本无关。这是关于从源代码构建并执行“make install”之类的操作时安装的默认发布版本。
  • 库的默认发布版本应该产生两个版本的库,一个用于调试要链接的程序的版本,另一个用于要链接的程序的发布版本。调试 是另一回事。
  • @JimBalter 问题是默认情况下是否应该为非调试版本的库打开断言。

标签: c++ c build


【解决方案1】:

我想我现在已经弄清楚了。定义 NDEBUG 的问题在于它可能导致未定义的行为。我的是一个包含一些非模板部分的模板库,所以我的代码被内联到其他人的二进制文件中。如果我在编译非内联代码时定义了 NDEBUG,然后在没有 NDEBUG 的情况下编译了客户端代码,那么标头中的代码将有两个不兼容的版本——一个带有断言,一个没有。这会导致未定义的行为,我曾经遇到过这个问题,因为我遇到过一次神秘的崩溃。所以我不认为图书馆应该定义 NDEBUG - 负责在给定计算机上编译所有内容的人或构建系统应该是决定 NDEBUG 的人。

但是,我不必定义 NDEBUG 只是为了让我的库在没有断言的情况下默认运行。我现在有一个宏 MYLIB_DEBUG 和 MYLIB_ASSERT。如果 MYLIB_DEBUG 未定义,则 MYLIB_ASSERT(X) 什么也不做。如果定义了 MYLIB_DEBUG,则 MYLIB_ASSERT(X) 定义为 assert(X)。这使得断言可以选择加入而不会弄乱 NDEBUG。

所以我目前对我的问题的回答是,默认情况下库可以关闭断言,如果你的接口有任何包含断言的内联函数,请不要通过定义 NDEBUG 来做到这一点。

【讨论】:

    【解决方案2】:

    如果使用 assert 会使您的库变慢,请按照您的意愿将其关闭。确保它被清楚地记录在案……别再担心了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-07-09
      • 1970-01-01
      • 1970-01-01
      • 2010-11-19
      • 2016-11-13
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多