内存分配是在编译时完成的吗 什么是虚拟内存?2M内存空间什么意思?

operatingtuzi 2009-02-25 03:18:51
1
常听说系统给每个函数的空间只有2M 为什么是2M呢 这个是说虚拟内存吗
2
什么是虚拟内存?这个是我们平时在硬盘里设置的那个吗?那不是想多大就多大?
3
普通变量(非new动态分配)是在编译的时候就分配内存吗?物理还是虚拟?还是只是知道要分配多大 实际并没有分配?
new在堆中分配是编译的时候不知道有多大吗?运行时直接分配,不经过虚拟内存?
...全文
658 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
pengzhixi 2009-03-11
  • 打赏
  • 举报
回复
mark
operatingtuzi 2009-03-11
  • 打赏
  • 举报
回复
继续等待回答。。
rgmlkthh 2009-03-06
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 dongpy 的回复:]
引用 6 楼 operatingtuzi 的回复:
还有 程序在编译的时候 是不是只是在虚拟地址上绑定了每个局部变量的位置 比如数组a在地址0x000...然后在运行的时候,再加上一个偏移量,比如0x12ff..  然后运行的时候隐射到物理地址0x12ff..呢
那么 实际上是编译的时候映射,运行的时候分配?
如果是这样的话 那静态变量和全局变量的处理有什么不同吗,它编译的时候难道就知道实际的物理地址?怎么知道的?

局部变量是通过寄存器加偏移量…
[/Quote]
你头像是你小时後的哇??看起来多帅。
operatingtuzi 2009-03-05
  • 打赏
  • 举报
回复
我知道栈空间满了是什么样了。。
不过还不到2M呢
大概1024*1010就满了。。

不过还是有些问题
静态绑定和动态绑定是怎么回事?
多态是动态绑定吧?
dongpy 2009-02-25
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 operatingtuzi 的回复:]
还有 程序在编译的时候 是不是只是在虚拟地址上绑定了每个局部变量的位置 比如数组a在地址0x000...然后在运行的时候,再加上一个偏移量,比如0x12ff.. 然后运行的时候隐射到物理地址0x12ff..呢
那么 实际上是编译的时候映射,运行的时候分配?
如果是这样的话 那静态变量和全局变量的处理有什么不同吗,它编译的时候难道就知道实际的物理地址?怎么知道的?[/Quote]

局部变量是通过寄存器加偏移量来寻址的,[ebp+N],N是编译时常数。
编译的时候不用知道也无法知道物理地址,静态变量和全局变量都在数据段,启动时分配内存。

0x12ff..不是物理地址,物理地址存储在pageframe中。
dongpy 2009-02-25
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 operatingtuzi 的回复:]
恩 我知道虚拟内存和物理内存的关系了

但是 还有一些疑问
每个进程2M的空间是不是就是只的栈空间?那如果定义了很多局部变量 都是大型数组或深层递归之类很占空间的东东,栈空间会不会满呀?要是满了怎么办?运行的时候程序会跳出一个异常显示栈溢出?
[/Quote]
程序操作不当时,会引起栈溢出,使进程退出。
所以,很大的对象,大数组不宜在堆栈定义,递归层次不宜太深。
Sco_field 2009-02-25
  • 打赏
  • 举报
回复
每个进程2M的空间是不是就是只的栈空间?那如果定义了很多局部变量 都是大型数组或深层递归之类很占空间的东东,栈空间会不会满呀?要是满了怎么办?运行的时候程序会跳出一个异常显示栈溢出?

-----------

当然会满,不过满了具体怎么实现,是固定分配的还是采用交换技术得看操作系统是怎么实现的了吧
operatingtuzi 2009-02-25
  • 打赏
  • 举报
回复
恩 我知道虚拟内存和物理内存的关系了

但是 还有一些疑问
每个进程2M的空间是不是就是只的栈空间?那如果定义了很多局部变量 都是大型数组或深层递归之类很占空间的东东,栈空间会不会满呀?要是满了怎么办?运行的时候程序会跳出一个异常显示栈溢出?


还有 程序在编译的时候 是不是只是在虚拟地址上绑定了每个局部变量的位置 比如数组a在地址0x000...然后在运行的时候,再加上一个偏移量,比如0x12ff.. 然后运行的时候隐射到物理地址0x12ff..呢
那么 实际上是编译的时候映射,运行的时候分配?
如果是这样的话 那静态变量和全局变量的处理有什么不同吗,它编译的时候难道就知道实际的物理地址?怎么知道的?
dongpy 2009-02-25
  • 打赏
  • 举报
回复
楼主的对虚拟内存和虚拟地址的理解有些不清楚。

1
常听说系统给每个函数的空间只有2M 为什么是2M呢 这个是说虚拟内存吗
================================================================
2M是进程的用户地址空间的一段连续空间,这是线程堆栈,大小是可以设置的。
进程地址空间是逻辑地址,也叫虚拟地址,分页系统是通过页表映射到物理地址的。

2
什么是虚拟内存?这个是我们平时在硬盘里设置的那个吗?那不是想多大就多大?
=================================================================
虚拟内存就是交换文件。物理内存短缺时,会换出一部分数据到交换文件中。

3
普通变量(非new动态分配)是在编译的时候就分配内存吗?物理还是虚拟?还是只是知道要分配多大 实际并没有分配?
new在堆中分配是编译的时候不知道有多大吗?运行时直接分配,不经过虚拟内存?
==============================================================================================
静态内存在编译链接后,在可执行文件中有一个副本,可以说是编译时就分配的。
程序启动时,直接映射到内存。
具体步骤:系统给进程建立一个逻辑段(即数据段),然后通过页表映射物理内存,再将数据导入内存。

堆内存分配时,编译器是不知道大小的。是通过C库里的malloc函数完成分配的。
waizqfor 2009-02-25
  • 打赏
  • 举报
回复

1
常听说系统给每个函数的空间只有2M 为什么是2M呢 这个是说虚拟内存吗
2
什么是虚拟内存?这个是我们平时在硬盘里设置的那个吗?那不是想多大就多大?
3
普通变量(非new动态分配)是在编译的时候就分配内存吗?物理还是虚拟?还是只是知道要分配多大 实际并没有分配?
new在堆中分配是编译的时候不知道有多大吗?运行时直接分配,不经过虚拟内存?

1 2M空间是系统自动划分出来的 专门给变量在栈上申请内存准备的 这个不是虚拟内存

2 内存在计算机中的作用很大,电脑中所有运行的程序都需要经过内存来执行,如果执行的程序很大或很多,就会导致内存消耗殆尽。为了解决这个问题,Windows中运用了虚拟内存技术,即拿出一部分硬盘空间来充当内存使用,当内存占用完时,电脑就会自动调用硬盘来充当内存,以缓解内存的紧张。举一个例子来说,如果电脑只有128MB物理内存的话,当读取一个容量为200MB的文件时,就必须要用到比较大的虚拟内存,文件被内存读取之后就会先储存到虚拟内存,等待内存把文件全部储存到虚拟内存之后,跟着就会把虚拟内里储存的文件释放到原来的安装目录里了。下面,就让我们一起来看看如何对虚拟内存进行设置吧。

3 你说的普通变量 是局部变量吗 应该是在栈 只要不是用malloc或new分配的空间 都是在栈 另外还有就是全局变量和静态变量 存储在静态区 等等
局部变量是有实际地址的 在声明的时候 系统就自动给它分配了大小 要按系统的字节大小来计算 这里不通过虚拟内存
lingyin55 2009-02-25
  • 打赏
  • 举报
回复
new在堆中分配是编译的时候不知道有多大吗?运行时直接分配,不经过虚拟内存?

这个应该和虚拟内存没有直接的关系吧,一般只有当计算机的随机访问内存 (RAM) 存储空间很少,并且需要更多空间才能完成当前的任务时,Windows 会使用硬盘空间(虚拟内存)模拟系统 RAM。
lingyin55 2009-02-25
  • 打赏
  • 举报
回复
to 那不是想多大就多大?

当然不能超过实际的空间大小,不过设置大了就浪费了,一般设置多大网上很多介绍。
lingyin55 2009-02-25
  • 打赏
  • 举报
回复
1,不是虚拟内存,是系统分配给应用程序的栈空间大小。
2,虚拟内存是为了满足系统对超出物理内存容量的需求时在外存(如硬盘)上开辟的存储空间。
由于虚拟内存其实是放在外存上,因而与物理内存相比读写速度都非常慢。
3,是堆和栈的问题,普通变量(非new动态分配)存储在栈,见第1条回答

一个由c/C++编译的程序占用的内存分为以下几个部分:
1、栈区(stack)— 由编译器自动分配释放,存放函数的参数值,局部变量的值等。其操作方式类似于数据结构中的栈。

2、堆区(heap) — 一般由程序员分配释放,若程序员不释放,程序结束时可能由OS回收。注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

3、全局区(静态区)(static)—,全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。 - 程序结束后由系统释放。

4、文字常量区 —常量字符串就是放在这里的。程序结束后由系统释放。

5、程序代码区—存放函数体的二进制代码。

一个经典的例子

//main.cpp
int a = 0; //全局初始化区
char *p1; //全局未初始化区
main()
{
int b; //栈
char s[] = "abc"; //栈
char *p2; //栈
char *p3 = "123456"; //123456\0在常量区,p3在栈上。
static int c =0;//全局(静态)初始化区
p1 = (char *)malloc(10);
p2 = (char *)malloc(20);
//分配得来得10和20字节的区域就在堆区。
strcpy(p1, "123456");
//123456\0放在常量区,编译器可能会将它与p3所指向的"123456"优化成一个地方。
}

65,211

社区成员

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

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