0

在使用未设置的局部变量或在初始化之前直接访问类或结构的成员时,捕获一些非常明显的错误非常好。在 Visual Studio 2008 中,您会在编译时收到“使用未初始化的局部变量”警告,并在调试时在访问点收到运行时检查失败。

但是,如果您通过其函数之一访问未初始化结构的成员变量,您不会收到任何警告或断言。显然,最简单的解决方案是不要那样做,但没有人是完美的。

例如:

struct Test
{
    float GetMember() const { return member; }
    float member;
};
Test test;
float f1 = test.member;      // Raises warning, asserts in VS debugger at runtime
float f2 = test.GetMember(); // No problem, just keeps on going

这让我感到惊讶,但它有一定的意义——编译器不能假设在未使用的结构上调用函数是一个错误,或者你将如何初始化或构造它?而且任何更高级的东西都会很快带来许多其他复杂性,以至于它不会费心分类哪些函数可以调用以及何时调用,尤其是作为调试帮助。我知道我可以在类本身中设置自己的断言或错误检查,但这会使一些更简单的结构复杂化。

尽管如此,它似乎在函数调用的上下文中,它不知道尚未初始化的内部GetMember()member?我假设它不仅依赖于静态编译时推导,因为Run-Time Check Failure #3它在执行期间引发,所以根据我目前对它的理解,应用相同的检查似乎是合理的。这只是这个特定编译器/调试器(Visual Studio 2008)的限制,还是更多地与 C++ 的工作方式相关?

4

1 回答 1

2

您可能会注意到警告是关于test未初始化的。这就是为什么警告和运行时故障仅适用于该行

float f1 = test.member;

这会导致未定义的行为,并且至少在调试模式下,MSVS 会进行一些检查并且能够崩溃(在发布时,该错误可能会被隐藏,并且您最终会得到一个虚假的值f1)。

然而,下一行不会直接导致 UB。f1没有被读取,也没有它的任何数据成员(直接)。调用了一个方法,编译器不知道该成员函数会在未初始化的对象上产生 UB。该函数可以只在屏幕上打印一些内容而不读取任何成员,这没关系。好吧,编译器理论上可以知道,因为它看到了代码,但它并没有深入挖掘。静态代码分析器可能会提醒您该问题。

于 2012-09-08T21:42:47.090 回答