当前位置: 首页 > 知识库问答 >
问题:

是否有超出翻译限制的未定义行为,是否有检查工具可以找到?

宇文和昶
2023-03-14

在编写高度可移植的代码时,我正在搜索C90标准以寻找需要注意的事情,同时对编译器供应商的善意不太信任,并且假设如果我做错了事情,我的软件有时可能会杀死某人。假设我有点偏执。

目前我正在考虑“翻译限制”(5.2.4.1 ANSI/ISO 9899:1990)。正如标准和中所指出的:“ansi C是否对程序中的外部变量数量进行了限制?”,这些是符合标准实施的最低要求。另一方面,这意味着,任何实现都不需要做更多的事情——如果我想确保我的代码适用于任何confrom实现,这些限制对我来说代表绝对限制。

到目前为止很烦人。

因此,编译器供应商选择的限制等于或高于所需的最小转换限制。

如果超过了特定实现的这些实现定义的转换限制,现在会发生什么?在我的ANSI/IO 9899:1990(C90)副本中,我没有发现任何东西,因此我认为这是未定义的“3.kind”(通过省略)行为。另一方面,这不是第一次,我误解了标准或者没有找到正确的段落。

以下是我的问题:

>

C90行为是否适用于C95/C96之前的修正版本和新的C99迭代

有没有人见过一个检查工具,可以检查最小的或(工具)用户定义的限制?

1) 正如Michael Burr在对该问题的直接评论中指出的那样,根据C标准(我只检查了C90,没有更正,以及C99草案,Michael在这里引用),conform C实现只需要接受一个同时包含所有限制的程序,这在最严格的解释中会取消任何最低限制保证。

2) 正如rubenvb和Keith Thompson指出的那样,一些质量的实现应该为这种情况提供诊断,即它们超出了实现定义的限制,尤其是当它们不符合最低要求时(rubenvb在评论中链接了MSVC的一个例子)。

3) 由于超出编译器限制可能是未定义的行为,但肯定会导致一些错误,因此我的某段代码的翻译限制所适用的“变量”值代表了重用的先决条件。

1) 因此,对于最大程度的妄想症,我会出丑,并要求编译器供应商向我保证,实现选择的限制适用于任何程序,以此来激怒编译器供应商的支持-(

2) 因此,我将调查编译器文档和编译器支持的承受能力,以获得确认,即:-对于每个翻译限制,如果超过,将提出诊断,并且-因为它是未定义的行为,如果每一个超过翻译限制的实例都会引发诊断,否则另一个错误已经阻止了编译。

3) 因此,我将尝试使用一种工具(如果我真的必须的话,也可以自己开发),来度量这些值,并将它们作为程序代码重用的先决条件。正如基思·汤普森(Keith Thompson)在回答中指出的那样,一些价值观可能需要更深入地了解如何实现。。。已实施。我不太确定在这种情况下,除了第2条中的行动之外,还有什么能起到帮助作用。)然而,在我看来,我必须进行测试——但我只需要测试是否存在UB(没有诊断),如果是这种情况,成功的测试不能保证一般情况下的正确性。

是的,这是痴迷的未定义行为。

基思·汤普森(Keith Thompson)在他的(公认的)anwser中用C标准文档的术语和参考说明了这是未定义的行为。

评论者尚未(尚未)发现检查代码中交易限制的工具。如果任何拥有(甚至部分)此功能的人使用了某个工具,请留下答案或评论。

共有3个答案

曾新
2023-03-14

在某些环境中,应用程序可能会收到等于总可用存储器的堆栈空间,减去代码和静态数据的组合大小。如果在努力运行程序之前无法知道可用存储器的数量,那么编译器、链接器或任何其他此类工具可能无法知道它是否足够。标准中的任何内容都没有对在内存不足以处理其堆栈要求时尝试运行程序时必须发生的事情提出任何要求。

如果该标准提供了一种方法,使程序在使用任何可用内存运行时都能确保某种程度的可预测行为,那将是很有帮助的,但目前它没有这样做。在许多平台上,都会有一些可用内存,这些内存足够大,操作系统加载程序不会拒绝可执行文件,但仍然足够小,应用程序几乎在启动时立即出现堆栈溢出。C标准的作者不想声明C不能与这样的平台一起使用,但他们也不能真正说明平台在使用如此关键的内存量运行代码时会做什么。

红甫
2023-03-14

这不是未定义的行为,而是实现定义的行为。这意味着这一切都取决于编译器。

是的,最低限度的实施指南保持不变,或者针对较新的标准版本进行了扩展。

您可能可以使用Clang来实现这一点,但您需要自己使用Clang API编写工具,我不知道有什么现成的实现。

在任何情况下:限制不是由标准设定的,“它们更像是指南”(实际上只不过是指南)。你需要检查你用来构建代码的编译器,看看你是否达到了极限,而不是仅仅在别人的鼻子里挥舞标准文档。由于MSVC的实现特别糟糕,我甚至敢说,如果它编译了你的代码(假设代码本身没有非法构造),你就相当安全了。

文华美
2023-03-14

我相信行为是未定义的。

该标准要求对任何违反约束或语法规则(N15705.1.1.3)的翻译单元进行诊断,并且可能无法成功翻译包含在预处理阶段幸存的#error指令的翻译单元(n1570 4,第4段)。(N1570是C11标准的草案,但C90、C99和C11之间是相同的,除了#error是由C99添加的。)

标准中明确规定了所有约束和语法规则。超过实现定义的限制既不违反约束也不违反语法规则。我认为,很明显,成功处理超出翻译限制的正确程序不需要实现,但标准没有说明它应该如何应对这种违反。因此,该行为未被遗漏定义。

(质量良好的实施将发布一个诊断,说明已超过限制,但这不是标准所要求的。)

要回答你问题的第三部分,不,我没有听说过可以检查程序是否违反最小翻译限制的静态检查器工具。这样的工具可能非常有用,并且一旦你有了C解析器,编写起来可能不会太难。对于对象大小的限制(C90中的32767字节,C99和C11中的65535字节),它必须知道编译器如何确定对象大小;int arr[30000];可能会也可能不会超过65535字节,具体取决于sizeof(int)。如果有人已经实现了这样的工具,而我只是没有听说过它,我不会太惊讶。

请注意,大多数实现没有施加标准允许的固定限制;相反,任何限制都是由编译时可用的内存资源施加的。

该标准确实以一种相当奇怪的方式提出了翻译限制。我特别想到的条款是:

实施应能够翻译和执行至少一个程序,该程序至少包含以下每一个限制的一个实例:

(这是C90、C99和C11中的5.2.4.1部分)。因此,不正当的实现可能只接受一个程序并拒绝所有其他程序。

我认为关键是,指定所有实现必须满足的合理限制是不切实际的。该标准可能会说,所有实现都必须始终接受至少32767字节的对象——但是,一个定义了一百万个这样的对象的程序呢?这些限制以极其复杂的方式相互作用,而相互作用的性质取决于每个编译器的内部结构。(如果您认为可以比C标准更好地定义翻译限制的要求,我鼓励您尝试。)

相反,本标准以这样一种方式陈述了需求,即实现一个遵循本标准字母的有用编译器的最简单方法是实现一个遵循本标准精神的有用编译器,不施加任何不合理的限制。符合标准的无用编译器是可能的,但不相关;我不知道有谁实现过这样的东西,我相信没有人会尝试使用它。

 类似资料:
  • 如何检查URL是否是必须是PNG、GIF或JPG格式的图像URL 我看到它可以通过以下代码完成: 但是,我需要使用或进行检查。 如何使用上面提到的两种技术来实现这一点?

  • 问题内容: 我想知道是否有一个gcc宏可以告诉我Linux内核版本,以便我可以适当地设置变量类型。如果没有,我将如何定义自己的宏呢? 问题答案: 在 LINUX / version.h中 的文件有一个名为宏可以让你检查要对当前的Linux版本头(版本)安装。例如,检查当前的Linux标头是否适用于内核 v2.6.16 或更早版本: 在运行时获取版本信息的更好方法是使用include / linux

  • 问题内容: 如果RPC没有超时机制,如果它试图调用已关闭服务器的RPC方法,该如何“杀死” RPC调用? 问题答案: 您可以使用渠道实施超时模式: 该会阻塞,直到返回或经过。

  • 我试图用vba做一个按钮来删除Excel表中的一行,但当我按下按钮并选择不止一行或许多单元格时,我想限制从E到I的选择(和行的数量无关)这里是我的代码,非常感谢,希望你能帮助我,我还没有找到任何类似的东西。

  • 问题内容: 具体说说(服务器端)V8,并假设我不担心准确性,因为我可以检测和补偿它,那么我可以使用setTimeout 逐字 间隔设置几千个相对简单的超时,而无需面对任何其他限制除了RAM以外?如果我要使用一个在任何给定时间可能有数千个计划的超时的系统,我应该注意什么吗? 作为记录,我已经阅读了John’s Resig关于Javascript计时器如何工作的出色文章,因此无需指出那里已经介绍的内容

  • 问题内容: 我期待的是类似WebElement.isfocus()的东西,…确实很简单,但是我发现的唯一方法是使用 伪类。 这真的是不常见的任务,例如找不到大量信息吗? 我知道这个SO主题,但是距那时已经快两年了。最新版本中没有新内容吗? 您知道一些解决方法吗? 问题答案: 还有另一个主题涉及这个问题:使用SeleniumWebdriver测试元素是否为焦点 基本上,代码将是