Mar*_*wen 19 c++ undefined-behavior language-lawyer
在关于未定义行为(UB)的许多讨论中,已经提出了这样的观点:在程序中存在任何具有UB的任何构造的程序都要求一致的实现做任何事情(包括什么都没有).我的问题是,即使在UB与代码执行相关联的情况下,是否应该采取这种方式,而标准中规定的行为(否则)规定不应执行相关代码(这可能是对于程序的特定输入;它可能在编译时不可判定).
更加非正式地说,UB的气味是否要求一致的实现来决定整个程序发臭,并且拒绝正确执行甚至行为完全明确定义的程序部分.一个示例程序将是
#include <iostream>
int main()
{
int n = 0;
if (false)
n=n++; // Undefined behaviour if it gets executed, which it doesn't
std::cout << "Hi there.\n";
}
Run Code Online (Sandbox Code Playgroud)
为清楚起见,我假设程序格式正确(因此特别是UB与预处理无关).事实上,我愿意将UB限制为与"评估"相关联,而"评估"显然不是编译时实体.我认为,与给出的例子相关的定义(重点是我的):
之前排序的是由单个线程(1.10)执行的评估之间的不对称,传递,成对关系,这导致这些评估之间的部分顺序
在运算符的结果的值计算之前,对运算符的操作数的值计算进行排序.如果对标量对象的副作用相对于...或使用相同标量对象的值进行值计算未被排序,则行为未定义.
隐含地清楚的是,最后一句中的主语"副作用"和"价值计算"是"评价"的实例,因为这就是定义"之前排序"的关系.
我认为在上述程序中,标准规定不进行评价,以满足最后一句中的条件(相对于彼此和所描述的类型),并且该程序不具有UB; 这不是错误的.
换句话说,我确信我的标题问题的答案是否定的.但是,我会很感激其他人对此事的(动机)意见.
对于那些主张肯定答案的人来说,可能还有一个问题是,当编译错误的程序时,会强制重新格式化硬盘吗?
本网站上的一些相关指针:
n. *_* m. 10
如果对标量对象的副作用相对于等等没有排序
副作用是执行环境状态的变化(1.9/12).更改是一种更改,而不是一种表达式,如果进行评估,则可能会产生更改.如果没有变化,则没有副作用.如果没有副作用,那么相对于其他任何事物都没有副作用.
这并不意味着任何从未执行过的代码都是无UB的(虽然我很确定它的大部分都是).标准中每次出现的UB都需要单独检查.(受到惊吓的文本可能过于谨慎;见下文).
该标准也说明了这一点
执行格式良好的程序的一致实现应该产生与具有相同程序和相同输入的抽象机的相应实例的可能执行之一相同的可观察行为.但是,如果任何此类执行包含未定义的操作,则此国际标准不要求使用该输入执行该程序的实现(甚至不考虑第一个未定义操作之前的操作).
(强调我的)
据我所知,这是唯一的规范性引用,它表示"未定义行为"这一短语的含义:程序执行中的未定义操作.没有执行,没有UB.
小智 6
编号示例:
struct T {
void f() { }
};
int main() {
T *t = nullptr;
if (t) {
t->f(); // UB if t == nullptr but since the code tested against that
}
}
Run Code Online (Sandbox Code Playgroud)
确定程序是否将执行整数除以0(即UB)通常等同于暂停问题.一般而言,编译器无法确定这一点.因此,仅仅存在可能的UB无法在逻辑上影响程序的其余部分:标准中对此影响的要求将要求每个编译器供应商在编译器中提供暂停问题解算器.
更简单, 仅当用户输入0时,以下程序才具有UB:
#include <iostream>
using namespace std;
auto main() -> int
{
int x;
if( cin >> x ) cout << 100/x << endl;
}
Run Code Online (Sandbox Code Playgroud)
认为这个项目本身就有UB 是荒谬的.
然而,一旦发生未定义的行为,就会发生任何事情:程序中代码的进一步执行会受到损害(例如,堆栈可能已被污染).
| 归档时间: |
|
| 查看次数: |
1117 次 |
| 最近记录: |