VS2008 函数内的局部变量为何地址不连续

R9R9R9 2009-07-10 01:26:29
#include "stdafx.h"
#include <cstdlib>
#include <iostream>

using namespace std;

void foobar()
{
int a = 10;
cout<<hex<<int(&a)<<endl;

int b = 20;
cout<<hex<<int(&b)<<endl;
}

int main(int argc, char *argv[])
{
foobar();

system("PAUSE");
return EXIT_SUCCESS;
}


output:

12fe8c
12fe80
Press any key to continue . . .


gcc下是连续的,印象中的VS也应该是连续的啊,空出来那么多的地址干啥啊,这不是浪费吗?
...全文
618 31 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
31 条回复
切换为时间正序
请发表友善的回复…
发表回复
pxdbxq 2012-08-31
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 的回复:]

听11楼的吧:)
[/Quote]
luojinping 2012-05-05
  • 打赏
  • 举报
回复
受益匪浅!
CrezySam 2010-09-26
  • 打赏
  • 举报
回复
受益。。。。
wangxipu 2009-12-01
  • 打赏
  • 举报
回复
re[Quote=引用 27 楼 prochsh 的回复:]
调试版一般都会多给出内存用来存放调试信息
[/Quote]
信念 2009-07-11
  • 打赏
  • 举报
回复
调试版一般都会多给出内存用来存放调试信息
liujianwish 2009-07-11
  • 打赏
  • 举报
回复
刚刚打错了
两个整型间差了12bytes,其中八4bytes是存放数据,还有8bytes是存放地址,大小,类型。。能让指针指得到用的~~还有就是揭示了sizeof为什么能求数据大小的问题~~想想光有个指针怎么能用sizeof求大小呢~~就是每个类型在内存里面前8个bytes保存了一些信息~~
liujianwish 2009-07-11
  • 打赏
  • 举报
回复
两个整型间差了12bytes,其中八8bytes是存放数据,还有4bytes是存放地址能让指针指得到用的~
机智的呆呆 2009-07-11
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 lw1a2 的回复:]
引用 8 楼 R9R9R9 的回复:
引用 5 楼 ltc_mouse 的回复:
用Release试试? 前几天好像有个帖子提到,说是VC在Debug时给变量留出空间,用来检查stack overflow的~


哦? 能否详细说说看?

《Windows程序调试》里面有解释
就是在变量周围塞些CCCCCCCC,越界了好出断言
[/Quote]
vs debug下,函数调用创建栈帧时,为局部变量预分配空间时,这一段空间全初始化化为cc,实际上是int 3指令,一个中断指令
debug时所下的断点,其实就是相当于插入的int 3指令。其作用个人认为是为了防止eip指针被恶意修改指向这些局部变量所在的
内存,并不是主要检查stack overflow的。而个人认为真正检查stack overflow的是GS编译选项,vs的这个编译选项,编译时ebp
除了push栈中,另外还会在pe文件中留有副本,函数调用完毕恢复栈帧时pop ebp时,通过跟副本的比较,从而确认是否stack overflow。
  • 打赏
  • 举报
回复
编译器爱怎么放就怎么放。甚至不放到栈中也是完全合法的。这都不是语言所限制的地方。
副组长 2009-07-11
  • 打赏
  • 举报
回复
对应用系统程序员来说纯粹是闲的蛋疼。
中才德创 2009-07-10
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 lw1a2 的回复:]
引用 8 楼 R9R9R9 的回复:
引用 5 楼 ltc_mouse 的回复:
用Release试试? 前几天好像有个帖子提到,说是VC在Debug时给变量留出空间,用来检查stack overflow的~


哦? 能否详细说说看?

《Windows程序调试》里面有解释
就是在变量周围塞些CCCCCCCC,越界了好出断言
[/Quote]有小例证明吗?
机智的呆呆 2009-07-10
  • 打赏
  • 举报
回复
这个可以连续也可以不连续~~~,
连续的话节省空间
不连续的话,一般经过对齐处理,能提高系统的性能,以空间换时间。
最终还是要到空间和时间这对矛盾上来~~~~~~~~~~
R9R9R9 2009-07-10
  • 打赏
  • 举报
回复
[Quote=引用 18 楼 baihacker 的回复:]
猪头饼怎么换E文了...
[/Quote]

晕。。。我比较喜欢洋妞

先顶下再看。
baihacker 2009-07-10
  • 打赏
  • 举报
回复
猪头饼怎么换E文了...
baihacker 2009-07-10
  • 打赏
  • 举报
回复

//其实这些在MSDN里面都写好了...只是你木有去查
//下面是我的测试结果
int a = 0;
int i;
cout << &a - &i << endl;
结果是1
编译选项为/RTCu
结果为3
编译选项为/RTC1
baihacker 2009-07-10
  • 打赏
  • 举报
回复
	int a = 0;
int i;
int arr[4];
for (i = 0; i < 6; ++i)
arr[i] = 0;

to15楼,我说了,参考5楼...堆栈检查...
0041BB36 call @ILT+1630(@_RTC_CheckStackVars@8) (417663h)
1
/RTCsu 的等效项。

c
当向较小的数据类型赋值从而导致数据丢失时报告。例如,当将类型 short 0x101 的值赋给类型 char 的变量时。

此选项报告您打算截断的情况,例如,您希望将 int 的前八位作为 char 返回的情况。因为 /RTCc 在由于赋值而丢失任何信息时将导致运行时错误,您可以屏蔽所需的信息以避免由于 /RTCc 而产生的运行时错误。例如:

复制代码
#include <crtdbg.h>

char get8bits(int value, int position) {
_ASSERT(position < 32);
return (char)(value >> position);
// Try the following line instead:
// return (char)((value >> position) && 0xff);
}

int main() {
get8bits(12341235,3);
}


s
启用堆栈帧运行时错误检查,如下所示:

将局部变量初始化为非零值。这有助于识别在调试模式下运行时不出现的 bug。因为在发布版本中编译器对堆栈变量进行优化,所以与发布版本相比,堆栈变量在调试版本中仍然为零的可能性更大。一旦程序使用其堆栈区域后,它就永远不会由编译器重置为 0。因此,恰好在随后使用相同堆栈区域的未初始化堆栈变量就可能返回上次使用该堆栈内存时留下的值。

检测局部变量(例如数组)的溢出和不足。/RTCs 将不检测当访问内存时由结构内的编译器填充导致的溢出。当使用 align (C++)、/Zp(结构成员对齐) 或 pack 时,或者以某种方式对结构元素进行排序以致要求编译器添加填充时,可能发生填充。

堆栈指针验证,该操作检测堆栈指针损坏。调用约定不匹配可能导致堆栈指针损坏。例如,使用函数指针调用 DLL 中作为 __stdcall 导出的函数,但将指向该函数的指针声明为 __cdecl。
u
当使用尚未初始化的变量时报告。例如,生成 编译器警告(等级 1)C4701 的指令也可能在 /RTCu 下生成运行时错误。生成 编译器警告(级别 1 和级别 4)C4700 的任何指令将在 /RTCu 下生成运行时错误。

然而,请考虑下列代码片段:

复制代码
int a, *b, c;
if ( 1 )
b = &a;
c = a; // No run-time error with /RTCu


如果变量可能已经初始化,则 /RTCu 在运行时将不报告。例如,在通过指针为变量起别名以后,编译器将不再跟踪此变量并报告未初始化使用。实际上,可以通过获取其地址来初始化变量。在这种情况下,& 运算符的作用类似于赋值运算符。

备注
运行时错误检查是发现运行的代码中的问题的一种途径;有关更多信息,请参见 如何:使用本机运行时检查。

如果在命令行上使用任一 /RTC 编译器选项编译程序,代码中的任何杂注 optimize 指令将失败而不给出任何提示。这是因为运行时错误检查在发布(优化)版本中无效。

对于开发版本,应该使用 /RTC;对于零售版本,不应该使用 /RTC。/RTC 不能与编译器优化 (/O 选项(优化代码)) 一起使用。与用 /Od 生成的映像相比,用 /RTC 生成的程序映像稍大一些,速度也稍慢一些(最多比 /Od 版本慢 5%)。

当使用任何 /RTC 选项或 /GZ 时,将定义 __MSVC_RUNTIME_CHECKS 预处理器指令。

在 Visual Studio 开发环境中设置此编译器选项
打开此项目的“属性页”对话框。有关详细信息,请参见如何:打开项目属性页。

单击“C/C++”文件夹。

单击“代码生成”属性页。

修改下列属性之一或两者都修改:“基本运行时检查”或“较小类型检查”。

以编程方式设置此编译器选项
请参见 BasicRuntimeChecks 和 SmallerTypeCheck 属性。
R9R9R9 2009-07-10
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 lw1a2 的回复:]
引用 8 楼 R9R9R9 的回复:
引用 5 楼 ltc_mouse 的回复:
用Release试试? 前几天好像有个帖子提到,说是VC在Debug时给变量留出空间,用来检查stack overflow的~


哦? 能否详细说说看?

《Windows程序调试》里面有解释
就是在变量周围塞些CCCCCCCC,越界了好出断言
[/Quote]

to 一刀:
谢了,有空我看看。


to baihacker:

[Quote=引用 11 楼 baihacker 的回复:]
听五楼的吧...
你想想,站在语言高度,应该对这种底层实现作出假设吗?
在上层,只看到定义了一个个的变量...凭什么要求连续分布?
如果你要说为了节省空间,又凭什么对存储作出假设,又为什么要求是线性存储,又凭一定要占有存储?
更可笑的是,有的人为了解释问题,就说看汇编吧?
这也是个逻辑上的错误,本来已经是那么样了,再去说,就是这么样的...
换句话说,看到的汇编可以认为是一种操作语义描述,是对既定语言的语义的一种解释.
在…
[/Quote]


不关C++语言的问题,我想问的是vs2008的编译器为何这样实现,因为之前版本的编译器好像都是连续,我今天不小心发现这个问题,提出来,想看看为何这样做,有啥优点而已。
Sou2012 2009-07-10
  • 打赏
  • 举报
回复
不同的超市,摆放商品的位置也不一样
kojie_chen 2009-07-10
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 baihacker 的回复:]
听五楼的吧...
你想想,站在语言高度,应该对这种底层实现作出假设吗?
在上层,只看到定义了一个个的变量...凭什么要求连续分布?
如果你要说为了节省空间,又凭什么对存储作出假设,又为什么要求是线性存储,又凭一定要占有存储?
更可笑的是,有的人为了解释问题,就说看汇编吧?
这也是个逻辑上的错误,本来已经是那么样了,再去说,就是这么样的...
换句话说,看到的汇编可以认为是一种操作语义描述,是对既定语言的语义的一种解…
[/Quote]
路过
Fleeboy 2009-07-10
  • 打赏
  • 举报
回复
听11楼的吧:)
加载更多回复(11)

65,186

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧