为什么在visual studio中连续的int数据类型变量位于12个字节的偏移
Why are consecutive int data type variables located at 12 bytes offset in visual studio?
为了澄清这个问题,请观察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 Arrays一节中声明"一个数组类型的对象包含连续分配的N个t类型的非空子对象集"。
这就是为什么array[]
将是连续的int
的集合,并且一个元素与下一个元素之间的差值将恰好是sizeof(int)。
对于本地/块变量(自动存储),没有这样的保证。唯一的语句在section 1.7中。c++内存模型:"每个字节都有一个唯一的地址。"和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 << "charn &b=" << &b <<
" +" << pb - pc << "charn &c=" << &c <<
" +" << pc - pd << "charn &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
所以你可以看到地址的顺序甚至可以在同一个编译器上改变,这取决于构建选项!!实际上,在释放模式下,变量是连续的,但顺序不同。
调试版本上的额外空格来自选项/rtc 。我故意用苛刻的memset()来覆盖变量,它假定它们是连续的。在退出执行时,我立即得到一条消息:"运行时检查#2,变量b周围的堆栈已损坏",这清楚地说明了这些额外字符的目的。如果删除该选项,您将得到MSVC13个连续变量,每个变量为4字节,正如您所期望的那样。但是也不会有更多关于堆栈损坏的错误消息。
- 从文件中读取多个字节,并将它们存储在C++中进行比较
- 为什么 bool 和 _Bool 如果它们在内存中占用 1 个字节,它们只能存储 0 或 1
- 在 Linux 中,uint32_t从 4 个字节更改为 6 个字节
- 运行时错误:引用绑定到类型"int"的未对齐地址0xbebebebebebebec6,这需要 4 个字节对齐 (stl_vector.h)
- 向指针地址添加 20 个字节偏移量
- 将(N 个字节)无符号字符指针转换为浮点数和双 C++
- C++/地址空间:每个地址 2 个字节?
- 为什么这个结构需要 24 个字节
- 为什么带有 vptr 的对象长 12 个字节?
- 使用 valgrind 检查我的链表暗示中的内存泄漏,让我"肯定丢失:1 个块中有 40 个字节"
- 复制后删除原始数组指针将前 3 个字节设置为 0
- 在编译时而不是运行时创建一个由两个字节组成的值
- 为什么在我的实现中,所有数组都对齐到 16 个字节?
- 使用 Python 导出 4 个字节浮点数
- C++向指针地址添加 4 个字节
- 是否强制转换void**并将第一个字节设置为nullptr
- AES-128 CFB-8解密的前16个字节已损坏
- 需要帮助从12个字节生成新的24字节RGB查找阵列,或者是一种更好的编码方法
- 为什么__int64在结构中占用12个字节
- 为什么在visual studio中连续的int数据类型变量位于12个字节的偏移