visual-studio - 为什么在 Visual Studio 中连续的 int 数据类型变量位于 12 字节偏移处?

标签 visual-studio c++ c visual-studio-2013 stack

为了澄清问题,请观察c/c++代码片段:

int a = 10, b = 20, c = 30, d = 40; //consecutive 4 int data values.

int* p = &d; //address of variable d.

现在,在 Visual Studio(2013 年测试)中,如果 p == hex_value 的值(可以在调试器内存窗口中查看),那么,您可以观察到其他变量 a、b、c 的地址,和 d 各相差 12 字节!

所以,如果 p == hex_value,则如下:

&c == hex_value + 0xC(注意十六进制 C 是十进制的 12)

&b == &c + 0xC

&a == &b + 0xC 

那么,为什么会有 12 个字节的偏移而不是 4 个字节—— int 只是 4 个字节?

现在,如果我们声明一个数组:

int array[]  = {10,20,30,40};

值 10, 20, 30, 40 与预期的相差 4 个字节!

谁能解释一下这种行为?

最佳答案

标准 C++ 在 8.3.4 数组 节中声明,“数组类型的对象包含一个连续分配的非空集,由 N 个 T 类型的子对象组成。”

这就是为什么 array[] 将是一组连续的 int,并且一个元素和下一个元素之间的差异将恰好是 sizeof(int)。

对于本地/ block 变量(自动存储),不提供这样的保证。唯一的陈述在 1.7 节中。 C++ 内存模型:“每个字节都有一个唯一的地址。”1.8。 C++ 对象模型:“该对象的地址是它占用的第一个字节的地址。两个对象 (...) 应具有不同的地址”

因此,假设此类对象的连续性所做的一切都是未定义的行为且不可移植。您甚至无法确定创建这些对象的地址的顺序。

现在我已经使用了你的代码的修改版本:

int a = 10, b = 20, c = 30, d = 40; //consecutive 4 int data values.
int* p = &d; //address of variable d.
int array[] = { 10, 20, 30, 40 };
char *pa = reinterpret_cast<char*>(&a), 
     *pb = reinterpret_cast<char*>(&b), 
     *pc = reinterpret_cast<char*>(&c), 
     *pd = reinterpret_cast<char*>(&d);
cout << "sizeof(int)=" << sizeof(int) << "\n &a=" << &a << \
  " +" << pa - pb << "char\n &b=" << &b << \
  " +" << pb - pc  << "char\n &c=" << &c << \
  " +" << pc - pd << "char\n &d=" << &d;
memset(&d, 0, (&a - &d)*sizeof(int));    
// ATTENTION:  undefined behaviour:  
// will trigger core dump on leaving 
// "Runtime check #2, stack arround the variable b was corrupted". 

运行此代码时,我得到:

debug                   release                comment on release

sizeof(int)=4           sizeof(int)=4       
 &a=0052F884 +12char     &a=009EF9AC +4char
 &b=0052F878 +12char     &b=009EF9A8 +-8char   // is before a 
 &c=0052F86C +12char     &c=009EF9B0 +12char   // is just after a !!
 &d=0052F860             &d=009EF9A4

所以你看到地址的顺序甚至可以在同一个编译器上改变,这取决于构建选项!事实上,在 Release模式下,变量是连续的,但顺序不同。

调试版的多余空格来自选项/RTCs .我故意用苛刻的 memset() 覆盖变量,假设它们是连续的。退出执行后,我立即收到一条消息:“运行时检查 #2,围绕变量 b 的堆栈已损坏”,这清楚地表明了这些额外字符的用途。
如果您删除该选项,您将获得 MSVC13 连续变量,每个 4 个字节,如您所料。但是也不会再有关于堆栈损坏的错误消息。

关于visual-studio - 为什么在 Visual Studio 中连续的 int 数据类型变量位于 12 字节偏移处?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25442458/

相关文章:

c# - C# 应用程序启动时出现 fatal error

visual-studio - Visual Studio makecert DES3 证书

c++ - 为具有一种方法的 IE 编写一个简单的 ActiveX 控件

c++ - 访问对象void pointer c++的成员

android - QT Visual Studio 2013 编译跨平台 : Windows, Android

c# - Visual Studio : Can't load 2 versions of Json. NET 和使用别名

c++ - 没有 OpenGL 的 Linux 基本图形编程

C语言增量(我认为)

c - 您的明星设计有多少行?

c - typedef struct 和 extern 声明的未知类型名称错误 - C 语言