gpt4 book ai didi

c++ - 我可以在下面的代码中使用任何编译器标志来报告有关 UB 的警告吗?

转载 作者:行者123 更新时间:2023-11-30 01:04:16 25 4
gpt4 key购买 nike

我对 GCC 编译器不是很熟悉,我正在尝试使用 wandbox 中的两个源文件运行代码.让我们从使用主文件(默认)和名为 other.cc 的第二个源文件的第一个代码开始。 ,如下:

主文件

#include <iostream>
struct A {
int i = 1;
static const int k = 1;
};
extern A a; // The object a is defined in other.cc

int main() {
std::cout << a.i << '\n';
std::cout << a.k << '\n';
}

other.cc

struct A {
int i = 1;
static const int k = 1;
};
A a{2};

请注意,我必须插入文件名 other.cc在 Wandbox 左侧的 Compiler Options 框中,以便编译此文件并将其链接到最终目标文件中。运行这段代码,我得到下面打印的数字 2 和 1,它们是正确的。

2
1

现在,如果我排除文件 other.cc从编译和链接过程中,通过从编译选项框中删除它的名称,我得到一个链接错误,关于对非静态数据成员的引用 A::i在表达式中使用

std::cout << a.i << '\n';

如果我随后从代码中删除这条语句,它显然运行正常,因为编译器替换了变量 a.k通过其在剩余语句中的常量值 1 std::cout << a.k << '\n';在 main() 中,打印 1。但根据 [basic.def.odr]/10,这被认为是未定义的行为和 [intro.compliance]/2 (2.3) .请注意 [basic.def.odr]/10 中提到的“无需诊断”。

在这种情况下,我试图通过使用一些阻止这种优化的标志来强制编译器发出错误。我已经尝试使用标志 -fkeep-static-consts-fno-keep-static-consts ,无济于事。我可以使用任何其他标志来避免这种未定义的行为吗?

我从 this discussion 得到这个例子在 C++ 标准讨论中。

我知道通过定义对象 a在第一个文件中可以解决问题。但这不是我要用这个奇怪的例子寻找的。我只是想更好地了解编译器在这些异常情况下的工作方式。

最佳答案

我认为另一个问题的答案会更有启发性。对未定义行为的恐惧在于使用不同的编译器时无法保证相同的运行时结果。所以:

我不需要错误消息来确保运行时行为不依赖于所使用的编译器吗?不。有两种情况需要考虑。

第一种情况:编译器将 a.k 替换为值 1。运行时行为是预期的结果。

第二种情况:编译器不会用固定值替换a.k,而是生成一些引用a 变量的机器代码。 (这就是您尝试使用编译器选项触发的内容。)在这种情况下,链接器会看到引用,并且当在任何翻译单元中都找不到该变量时将发出错误。您无法进展到运行时行为,因此您不会获得与第一种情况不一致的运行时结果。

因此理论上在切换编译器时可能会有一些痛苦,但不会出现未定义行为典型的隐蔽错误。

如果有些人觉得这个答案没有启发性,我现在回到原来的问题,稍微改写一下。

当发生这种违反单一定义规则的情况时,是否有任何标志可以用来强制显示诊断消息(错误或警告)?取决于编译器,但可能不是。请注意 [basic.def.odr]/10 提到“不需要诊断”,因此当发生此特定违规时,编译器不需要提供诊断消息。为什么不?大概是由于上述原因:消息将在稍后阶段(即链接)触发,或者预期的行为将闪耀。在这种情况下,通过要求错误/警告来增加编译器的簿记负担没有任何好处。

关于c++ - 我可以在下面的代码中使用任何编译器标志来报告有关 UB 的警告吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50497854/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com