如何绕过Visual C++;不符合标准? 根据VisualC++ 2005(和2008/2010),不正确初始化数据成员。

如何绕过Visual C++;不符合标准? 根据VisualC++ 2005(和2008/2010),不正确初始化数据成员。,c++,visual-c++,C++,Visual C++,由于我有一个需要标准行为的代码,并且在发布模式(而不是调试模式)下崩溃,我怀疑问题来自这里 现在的问题是代码库相当大,手动检查类很困难 是否有编译器选项触发MSVC的此非标准行为的警告?使用/W4,您会收到关于一些非标准扩展(从右值到引用的转换,缺少typename关键字)的警告,但不是针对这个特定问题 编辑:我怀疑这样的代码会引起麻烦(从链接问题粘贴) 然后后来, if (b->m) { b->m->bar(); } 根据标准,b->m应该为零,但很可能不是(调试模式除外)

由于我有一个需要标准行为的代码,并且在发布模式(而不是调试模式)下崩溃,我怀疑问题来自这里

现在的问题是代码库相当大,手动检查类很困难

是否有编译器选项触发MSVC的此非标准行为的警告?使用/W4,您会收到关于一些非标准扩展(从右值到引用的转换,缺少
typename
关键字)的警告,但不是针对这个特定问题

编辑:我怀疑这样的代码会引起麻烦(从链接问题粘贴)

然后后来,

if (b->m) { b->m->bar(); }

根据标准,
b->m
应该为零,但很可能不是(调试模式除外)。我想检测这样的代码(比如一个警告“
m
未经初始化就使用了”或其他东西)

这是关于
foo::foo():member(){}
?粘贴您看到的问题的一些示例(代码)。在标准C++实现中,成员应该具有值0(假设它是基本类型)。但是,一些较旧的编译器没有正确地执行/实现这一点,只是将其保持为未初始化状态。好了,这没有任何警告。您必须遍历代码,并显式地用0或其他值初始化成员。

下面的注释是,在调用ctor之前,编译器应该是zero init

8.5 An object whose initializer is an empty set of parentheses, i.e., (), shall be
value-initialized. ... Value-initialization for such a class object may be implemented 
by zero-initializing the object and then calling the default constructor

12.1/7 A non-user-provided default constructor for a class ... performs the set of  
initializations of the class that would be performed by a user-written default 
constructor for that class with no ctor-initializer (12.6.2) and an empty
compound-statement.

12.6/4  If a given non-static data member or base class is not named by ... in 
initialiser   list ... the entity is not initialized. 

<>但是,记住有效的C++,如果你声明一个Dor,那么你也应该声明一个拷贝cTor、cTor和自赋值(即使你声明为私有)

你确定你(人们声称引用ISO C++标准)实际上引用它吗?并且没有与TR中规定的更新版本的文本混淆,这些版本实际上不是标准?或者C++11,可能很快就会出现,但人们很难期望MS符合尚未正式成为标准的东西。

不要绕过它,直接攻击它。

你需要一个C++解析器。使用解析器,您必须跟踪未在类的每个构造函数中正确分配的变量类型。一旦这样做了,只需插入适当的语法,就可以以理想的方式进行初始化。这不是一个简单的脚本编写,但它会节省你的头痛负载后

第一步是从解析树中获取输出,为您标记问题:

class Foo{
public:

    Foo(int a) : mA(a){}

private:

    int mA, mB;
};
您希望脚本在类Foo::缺少初始值设定项mB中生成如下消息:

然后获取并将该输出转换为指令集,以遍历解析树并插入缺少的项,从而使代码如下所示:

class Foo{
public:
    Foo(int a) : mA(a), mB(0){}

private:

    int mA, mB;
};

所以我最好的建议是不要试图绕过这个问题,直接攻击它。如果在这之后您仍然有问题,请使用最近的静态代码分析器和内存分析器。这些是最能帮助您的工具。

我目前正在诊断问题。正如我所说的,代码库相当庞大,我怀疑一些指针应该是零,而不是零(我在发布模式中遇到访问冲突异常)。我知道在我编写的代码中我默认初始化指针。编译器在调试中就像在发行版配置中一样损坏。@Hans:有些东西在调试模式下初始化为零,而在发行版中没有(我不知道到底是什么东西),我曾经遇到过这个问题,我怀疑是这样的。@Alexandre:一般来说,如果编译器认为某些内容应该未初始化,那么在调试模式下,它会将其初始化为某种奇怪的值,很可能是无效值,如0x5555。在这种情况下,如果调试模式将某些内容初始化为0,我会感到惊讶。@j_random_hacker:很高兴知道,谢谢。@@j_random_hacker:VC调试RTL将在将其交给应用程序之前清空所有内存。发布版RTL不会。示例代码上的
m
指针是我自己没有编写的遗留代码(这就是我试图调试的)。但是,
b
是一个
boost::shared_ptr
。这描述了非用户提供的默认构造函数将执行的操作,但是
new b()
值初始化新对象,它不使用非用户定义的默认构造函数。请参见8.5[dcl.init]。三的规则是一个指导原则,不包括默认构造函数。您是否应该提供默认构造函数通常是一个单独的问题,尽管通常在您提供“三个”时,您希望至少有一个用户声明的构造函数,而不仅仅是复制构造函数(默认或其他)。顺便问一下,您使用的是什么版本的标准?在没有用户声明的默认构造函数的类类型的对象的值初始化中,不会调用构造函数。这是从哪里来的?“此类类对象的值初始化可通过零初始化对象,然后调用默认构造函数来实现”是,请参阅ISO/IEC 14882:2003的8.5[dcl.init]。
class Foo{
public:

    Foo(int a) : mA(a){}

private:

    int mA, mB;
};
class Foo{
public:
    Foo(int a) : mA(a), mB(0){}

private:

    int mA, mB;
};