如果对表达式的求值导致C中的未定义行为,并且在执行程序时总是评估表达式(例如,如果它出现在main
的开头),那么如果实现拒绝,它是否符合要求它在编译时?在编译/翻译程序和执行程序之间,C有区别吗?
我知道有C语言翻译。如何通过C标准处理这种差异?
示例(读取未初始化的本地)
int main() { int i; return i; }
在运行它时,在执行的任何阶段(甚至在调用main
之前),程序可以做一些有趣的事情。但是,当我们甚至没有试图运行它时,还会发生一些有趣的事吗?它会在编译器本身中导致缓冲区溢出吗?
答案 0 :(得分:40)
从C11草案开始:
3.4.3未定义的行为
行为,使用不可移植或错误的程序结构或错误数据,本国际标准不强制要求
注意可能的未定义行为包括完全忽略具有不可预测结果的情况,以及在转换或程序执行期间以特定于文档的方式执行的行为。 环境(发出或不发布诊断消息),终止翻译或执行(发布诊断消息)。
在(非规范)注释中提到终止翻译是未定义行为的可能后果,因此编译时效果显然无意排除。规范部分肯定允许它 - 它允许任何东西。因此,如果在编译期间检测到未定义的行为,那么符合标准的编译器可以终止转换。
此外, $ 4一致性:
如果违反约束或运行时约束之外的''shall''或''shall not''要求,则行为未定义。未定义的行为在本国际标准中以“未定义的行为”或“省略行为的任何明确定义”的方式表示。这三者之间的重点没有区别;他们都描述了“未定义的行为”。
在规范性定义或“转换时间”之间的一致性描述中没有区别。和"执行时间"。不同品种之间没有差异,#34;未定义的行为。
此外,Defect Report #109中ouah指出的Can code that will never be executed invoke undefined behavior?在回复中有这样的说法:
[...]如果一个表达式的评估会导致未定义的行为出现在需要使用常量表达式的上下文中,则包含的程序并不严格符合。此外,如果给定程序的每个可能的执行都会导致未定义的行为,则给定的程序不严格符合。
符合标准的实现必须简单地转换严格符合的程序,因为该程序的某些可能执行会导致未定义的行为。 [...]
这表明如果编译器无法静态确定所有路径都会导致未定义的行为,则编译器不能使转换失败。
答案 1 :(得分:14)
在C11标准中,§3.7.1在术语未定义行为的定义下声明:
未定义的行为:使用不可移植或错误的程序构造或错误数据时的行为,本国际标准不对其施加任何要求
2注意可能的未定义行为包括完全忽略不可预测的情况 结果,在翻译或程序执行过程中以文件化的方式表现 环境(有或没有发出诊断消息),终止翻译或执行(发布诊断消息)。
所以我猜你可以静态拒绝包含未定义行为的程序,即使它是有效的。
答案 2 :(得分:5)
如果实现在编译时拒绝它,它是否符合要求?
可能会也可能不会。 C标准在第3.4.3节中说明了这一点:
C11:3.4.3 未定义的行为
在使用不可移植或错误的程序结构或错误数据时的行为,本国际标准不对其施加任何要求
- 醇>
注意可能的未定义行为包括完全忽略不可预测结果的情况,在翻译或程序执行期间以环境特征的文件形式表现(有或没有发布诊断消息),终止翻译或执行(发布诊断消息)。
回答你的问题:它会在编译器本身导致缓冲区溢出吗?
是的,可以。