未定义行为 (UB) 以实现余地为条件的程序是否为具有无条件 UB 的程序?
Is a program where undefined behavior (UB) is conditional on implementation leeway a program with unconditional UB?
在
的答案中
表明程序可能具有未定义的行为“取决于”(des Pudels Kern in this question) how an implementation used implementation leeway given by the standard. As an example, [expr.prim.lambda.closure]/2:
The closure type is declared in the smallest block scope, class scope,
or namespace scope that contains the corresponding lambda-expression. [...]
The closure type is not an aggregate type. An
implementation may define the closure type differently from what is
described below provided this does not alter the observable behavior
of the program other than by changing:
- (2.1) the size and/or alignment of the closure type,
- (2.2) whether the closure type is trivially copyable ([class.prop]), or
- (2.3) whether the closure type is a standard-layout class ([class.prop]). [...]
有人在对答案的评论中指出,这种情况不是实现定义的行为
"implementation-defined" has a very specific meaning ([intro.abstract]/2); this isn't a case of that.
一个有未定义行为 (UB) 的程序有条件地依赖于这样的实现余地,会不会有无条件的 UB,可能根据 [intro.abstract]/5?或者如何用标准术语描述这样的程序?
假设我理解正确,这里有一个更简单的例子:
void* storage = ::operator new(100);
new (storage) std::string;
在某些语言实现中,当字符串适合内存时,将定义此示例程序的行为。但是该标准不保证任何语言实现都满足该假设,并且在假设不成立的语言实现中,行为是未定义的。
该行为有条件地未定义,具体取决于语言实现。这同样适用于问题中描述的更微妙的例子。
这不是“实现定义”的行为,因为标准并没有说它是使用那些引用的词的“实现定义”。如果标准确实这么说,那就意味着语言实现必须记录该行为。实际上,不需要记录闭包类型是否可平凡复制。
为了避免这个短语具有特殊含义,我们可以使用“依赖于实现”或“未指定”等替代词来描述这种情况。
如果您希望编写可移植到当前标准的任何语言实现的程序,包括您目前无法知道其实现的未来存在的程序,您不应无条件地依赖此类实现细节。
您可以使用类型特征来观察闭包是否可平凡复制,并有条件地使用 std::bit_cast
仅当它格式正确且定义明确时 - 如果您有充分的理由这样做。
C 和 C++ 标准都没有被编写来完整描述各种平台和目的的实现应该或不应该有意义地处理程序的所有情况。术语“实现定义”仅在所有实现都需要指定一种行为的情况下使用,至少对于单个线程上的代码运行,该行为将与顺序程序执行一致。即使大多数实现应该以相同的方式处理构造,但如果可能存在某些实现,在这些实现中指定和实现始终可预测且与顺序程序执行一致的行为是不切实际的,则标准仍将使用术语“未定义行为”。除其他事项外,这适用于可能会产生标准未预料到的副作用的结构。例如,给定如下内容:
float x,y; // Assume at least one might not get written before the following:
float temp= x*y;
if (func1())
func2(temp);
如果不进一步使用 temp,实现可能会明智地推迟跨函数调用的乘法运算。但是,如果尝试乘以无效的浮点值可能会陷入困境,那么这种延迟的影响可能是可以观察到的。因为在标准未强制要求的情况下可以提供有用的有用行为保证的实现总是可以自由地这样做,无论标准是否需要这种行为,是否强制要求行为的问题只在以下情况下相关有意义地处理它是不切实际的实现。
在
的答案中表明程序可能具有未定义的行为“取决于”(des Pudels Kern in this question) how an implementation used implementation leeway given by the standard. As an example, [expr.prim.lambda.closure]/2:
The closure type is declared in the smallest block scope, class scope, or namespace scope that contains the corresponding lambda-expression. [...] The closure type is not an aggregate type. An implementation may define the closure type differently from what is described below provided this does not alter the observable behavior of the program other than by changing:
- (2.1) the size and/or alignment of the closure type,
- (2.2) whether the closure type is trivially copyable ([class.prop]), or
- (2.3) whether the closure type is a standard-layout class ([class.prop]). [...]
有人在对答案的评论中指出,这种情况不是实现定义的行为
"implementation-defined" has a very specific meaning ([intro.abstract]/2); this isn't a case of that.
一个有未定义行为 (UB) 的程序有条件地依赖于这样的实现余地,会不会有无条件的 UB,可能根据 [intro.abstract]/5?或者如何用标准术语描述这样的程序?
假设我理解正确,这里有一个更简单的例子:
void* storage = ::operator new(100);
new (storage) std::string;
在某些语言实现中,当字符串适合内存时,将定义此示例程序的行为。但是该标准不保证任何语言实现都满足该假设,并且在假设不成立的语言实现中,行为是未定义的。
该行为有条件地未定义,具体取决于语言实现。这同样适用于问题中描述的更微妙的例子。
这不是“实现定义”的行为,因为标准并没有说它是使用那些引用的词的“实现定义”。如果标准确实这么说,那就意味着语言实现必须记录该行为。实际上,不需要记录闭包类型是否可平凡复制。
为了避免这个短语具有特殊含义,我们可以使用“依赖于实现”或“未指定”等替代词来描述这种情况。
如果您希望编写可移植到当前标准的任何语言实现的程序,包括您目前无法知道其实现的未来存在的程序,您不应无条件地依赖此类实现细节。
您可以使用类型特征来观察闭包是否可平凡复制,并有条件地使用 std::bit_cast
仅当它格式正确且定义明确时 - 如果您有充分的理由这样做。
C 和 C++ 标准都没有被编写来完整描述各种平台和目的的实现应该或不应该有意义地处理程序的所有情况。术语“实现定义”仅在所有实现都需要指定一种行为的情况下使用,至少对于单个线程上的代码运行,该行为将与顺序程序执行一致。即使大多数实现应该以相同的方式处理构造,但如果可能存在某些实现,在这些实现中指定和实现始终可预测且与顺序程序执行一致的行为是不切实际的,则标准仍将使用术语“未定义行为”。除其他事项外,这适用于可能会产生标准未预料到的副作用的结构。例如,给定如下内容:
float x,y; // Assume at least one might not get written before the following:
float temp= x*y;
if (func1())
func2(temp);
如果不进一步使用 temp,实现可能会明智地推迟跨函数调用的乘法运算。但是,如果尝试乘以无效的浮点值可能会陷入困境,那么这种延迟的影响可能是可以观察到的。因为在标准未强制要求的情况下可以提供有用的有用行为保证的实现总是可以自由地这样做,无论标准是否需要这种行为,是否强制要求行为的问题只在以下情况下相关有意义地处理它是不切实际的实现。