【问题标题】:Visual C++ seems to be zero-initializing POD members of a class which it shouldn'tVisual C++ 似乎是零初始化一个它不应该的类的 POD 成员
【发布时间】:2019-04-19 10:51:24
【问题描述】:

我有这样的课:

class TestClass
{
public:
    TestClass() {};
    //Note: I wish not to initialize rawMemory (for whatever reason)
    int rawMemory[32];
};

int main()
{
    TestClass obj;
    return 0;
}

在我使用TestClass obj; 创建TestClass 对象后,我得到了我想要的行为:rawMemory 没有被初始化(在调试模式下填充为 0xcc,在发布模式下填充随机未确定的值)。
当我向类添加指针成员时:

class TestClass
{
public:
    TestClass() {};
    int rawMemory[32];
    int* ptr;
};

rawMemory 被初始化为零!我认为根据标准,这不应该发生。我什至尝试使用专用于保留未初始化的自动内存的std::aligned_storage,而rawMemory 仍然被零初始化!

class TestClass
{
public:
    TestClass() {};
    std::aligned_storage<sizeof(int), alignof(int)>::type rawMemory[32];
    int* ptr;
};

注意:我已经尝试过 g++,它按预期工作。
更新:如果我将 TestClass 更改为结构,问题就消失了;如果我给TestClass 一个默认的隐式构造函数,问题就消失了。

【问题讨论】:

  • 编译器实现是否允许这样做。标准中没有任何规定禁止这样做。此外,为rawMemory 分配的内存可能已经包含零。
  • 标准不要求初始化成员。这与要求将它们初始化为非零值不同。
  • @FawkesFlammer 为什么你会假设用零(或任何其他值)填充的内存已被初始化?
  • 仅仅因为内存的内容恰好为零并不意味着编译器实际上生成了将内存初始化为零的代码……零是内存中最常见的元素之一……
  • 但无论如何:您使用的是哪个版本的 Visual C++ 以及您使用哪些编译器标志进行编译?您确实意识到,出于安全原因,任何现代操作系统只会将您的进程归零内存页面吗?

标签: c++ visual-c++


【解决方案1】:

我终于找到了这个问题的根源。
当类中存在指针成员时,Visual C++ 在调用我定义的构造函数之前插入一个autoclassinit 方法调用。此方法调用在成员初始化方面有些混乱,它确实对我的 rawMemory 成员进行了零初始化
通过在 Visual C++ 编译器选项中禁用 /sdl 可以消除此行为。但是,如果它对性能不是很关键(或瓶颈),我的建议是保持原样。
感谢所有试图提供帮助的人!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-08-16
    • 2012-12-23
    • 2021-10-05
    相关资源
    最近更新 更多