【问题标题】:MSVC initialization of heap when padding is involved涉及填充时堆的 MSVC 初始化
【发布时间】:2012-01-14 16:20:55
【问题描述】:

MSVC 内存管理器在调试版本中使用某些十六进制代码来标记内存,具体取决于执行的操作。这些记录在here

特别是,代码 0xCDCDCDCD 用于标记已分配但未初始化的堆内存。假设我有以下结构:

struct Test
{
   bool foo;
   int value;

   Test() : foo(false), value(0) {}
};

当我分配这个对象时,我的内存会是这样吗(请注意,我正在写出十六进制字节,因为它们会按顺序显示,本示例未考虑字节序)?

00 CD CD CD CD 00 00 00 00

上面,00 CD CD CD 表示 4 字节对齐的布尔值。最后 3 个字节是 0xCD,因为内存管理器将这些值初始化为 CD,但是结构中该布尔值的实际初始化仅涉及 1 个字节,因为布尔值在我的机器上仅代表 1 个字节。

这是正确的行为吗?

【问题讨论】:

  • 只是好奇 - 你为什么要问?你为什么不检查一下?
  • 我之所以问,是因为我遇到了对齐问题,并且我看到了 00 CD CD CD 我的一个布尔成员所在的值,我只是想确认程序只是在初始化四个中的第一个字节。如果是这种情况,那么我可以解释为什么最后 3 个字节是 0xCD
  • @Robert,您不应该根据对齐部分的内容做出任何决定,因为它是实现定义的并且可以包含任何随机数据。

标签: c++ memory-management heap-memory msvcrt


【解决方案1】:

试试吧。确保使用/MDd 等进行编译以链接到调试运行时。 (在 VS2010 中答案是肯定的)。

【讨论】:

  • 查看调试版本中的行为并不是一个好策略。当优化器启动时,就会发生不寻常的事情。
  • @Hans,它是实现定义的,MSVC 的内存模式填充只发生在调试运行时。在优化的构建中行为将是相同的。调试运行时库二进制文件不会因为用户的代码被编译优化而改变,如果他仍然链接到调试运行时。
【解决方案2】:

如果生成更快的代码,没有什么可以阻止代码生成器写入 4 个字节。或者使用 memset(),这是 MSVC 编译器中的常见优化。但这显然没有发生。无论哪种方式都是正确的,读取结构填充是未定义的行为。

【讨论】:

    猜你喜欢
    • 2013-02-28
    • 2011-07-27
    • 2014-02-01
    • 1970-01-01
    • 2018-07-29
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多