【问题标题】:Can merely using (stable) third party library render my code not working只能使用(稳定的)第三方库使我的代码不起作用
【发布时间】:2015-11-19 07:35:16
【问题描述】:

假设我有 C++ 项目多年来一直运行良好。 还要说这个项目可能(需要验证)包含未定义的行为。 所以也许编译器对我们很友好,即使有 UB,也不会使程序行为不端。 现在想象一下我想为项目添加一些功能。例如向其中添加 Crypto ++ 库。 但是我从 Crypto++ 中添加的实际代码是合法的。 Here我看了:

如果您的代码是较大项目的一部分,则可以有条件地调用一些 第 3 方代码(例如,预览图像类型的 shell 扩展) 一个文件打开对话框)改变一些标志的状态(浮动 点精度、语言环境、整数溢出标志、除以零 行为等)。您的代码以前运行良好,现在显示 完全不同的行为。

但我无法准确判断作者的意思。他是否说即使在我的项目中添加说 Crypto ++ 库,尽管我添加的来自 Crypto++ 的代码是合法的,但我的项目可能突然开始无法正常工作?

这是现实的吗? 任何可以证实这一点的链接?

我很难向相关人员解释仅仅添加库可能会增加风险。也许有人可以帮助我制定如何解释这一点?

【问题讨论】:

  • 您发布的链接中没有说明所有内容吗?如果你的代码中有 UB,它几乎可以在任何时候出于任何原因中断。
  • 从技术上讲,添加库可以(并且很可能会)改变正在运行的应用程序的内存布局。动态内存可能分配在与以前不同的地址,并且代码可能映射到与以前不同的位置。假设您的写入超出了 100 个字节的范围 - 如果您在内存页面的开头执行此操作,则可能不会发生任何事情,但如果您在内存页面的末尾执行此操作,您可能会遇到分段错误。
  • 只是告诉人们,由于糟糕的开发实践,代码有很多年未被发现的严重错误,但现在鸡终于回家了。
  • 我不是在开玩笑。情况就是这样。你可以用更好的词来装扮它,但它就是这样。
  • @user200312 如果他们的代码包含 UB,那么即使没有添加这个新库,他们现在都处于危险之中。

标签: c++ undefined-behavior


【解决方案1】:

当源代码调用未定义的行为时,这意味着标准不保证会发生什么。它可以在一次编译运行中完美运行,但只需使用较新版本的编译器或库再次编译它可能会使其崩溃。或者改变编译器的优化级别也有同样的效果。

一个常见的例子是读取数组末尾的一个元素。假设您希望它为 null 并且 偶然 下一个内存位置在正常情况下包含 0(假设它是一个错误标志)。它将毫无问题地工作。但是现在假设在更改完全不相关的内容后的另一个编译运行中,内存组织略有改变,数组之后的下一个内存位置不再是那个标志(保持恒定值)而是一个取其他值的变量。您的程序会中断并且难以调试,因为如果将该变量用作指针,您可能会在随机位置覆盖内存。

TL/DR:如果一个版本有效,但您怀疑其中包含 UB,唯一正确的方法是在进行任何更改之前始终从代码中删除所有可能的 UB。或者,您可以保持工作版本不变,但请注意,您可能需要稍后更改它...

【讨论】:

  • @user200312:以上所有评论和我的回答都说同样的话:是的,只要涉及 UB,任何更改都可能使其中断。
  • @user200312:套用 Jacques Coeur 的座右铭:对于勇敢的心来说,没有什么是不可能的(在法语中,heart is coeur)。但是你应该先估计一下它的成本和时间......
  • 任何更改(包括编译器更新)都可能突然使长期隐藏的问题变得明显;要么你的项目永远保持不变,要么你必须处理这个问题。启动编译警告;运行调试构建;启用调试 STL;在 valgrind 下运行;使用地址清理程序编译。用 STL 结构替换固定大小的缓冲区(更易于检测且不易出错)。这些东西极大地帮助解决了我从事的一个大型旧项目中的许多错误,是的,添加新代码、添加大型库、更改时间等也确实暴露了隐藏的错误。
  • (另外:在完全不同的编译器下构建确实有帮助)
  • 其他选项是 1:祈祷一切顺利,或 2:持续审查和测试所有代码。他们都不是很好......
【解决方案2】:

多年来,C 已经变异为一种低级语言和高级语言的奇怪混合体,其中代码提供了对执行任务方式的低级描述,然后现代编译器尝试将将其转化为对任务是什么的高级描述,然后实现有效的代码来执行该任务(可能以与指定的方式非常不同的方式)。为了便于将低级步骤序列转换为正在执行的操作的高级描述,编译器需要对执行这些低级步骤的条件做出某些假设。如果这些假设不成立,编译器可能会生成以非常怪异的方式出现故障的代码。

使情况复杂化的事实是,如果规则的某些部分经过深思熟虑,许多常见的编程结构可能是合法的,但在编写规则时,它们会授权编译器做任何他们想做的事情。识别代码在哪些地方可以说应该是合法的,并且在历史上 99.999% 的时间都可以正常工作,但可能会因任意原因而中断,这可能非常困难。

因此,人们可能希望添加一个新库不会破坏任何东西,并且大多数时候一个人的愿望可能会实现,但不幸的是,很难知道任何代码中是否可能有潜伏的定时炸弹。

【讨论】:

  • 我认为我包含的库是稳定的
  • @user200312:我的意思是,您的代码 100% 稳定,可能会与标准中的一些奇怪的极端情况发生冲突,并向其中添加大量新代码系统可能会改变一些东西,从而使过去起作用的东西不再起作用。
猜你喜欢
  • 2018-10-25
  • 1970-01-01
  • 1970-01-01
  • 2022-12-06
  • 2015-12-19
  • 2017-05-18
  • 1970-01-01
  • 2012-06-21
  • 1970-01-01
相关资源
最近更新 更多