c语言,内存分配情况
想完全的搞清楚在运行一个程序的时候,内存是如何分配的,分配的多大的空间,顺序是怎么样的。网上看了不少资料哈,知道全局变量,局部变量,等在堆栈的存放,但是不全面。比如下面一个程序:
#include <iostream>
using namespace std;
int a,b[5];
int add(int x,int y)
{
int c;
c=x+y;
return c;
}
int main()
{
int d=2,e=3;
int f=add(d,e);
cout<<f<<endl;
}
程序开始运行的时候,操作系统是如何给这个程序分配空间的?分配的多大?(如何知道这个程序要多大的空间),然后各个变量(a,b,c,d,e,f,x,y)在内存中,是如何存放的?程序本身的代码又是放在哪里的?网上讨论这些的挺多,但是感觉不全面,希望有个比较全面的讲解,搞清楚。 谢谢各位给予详细的指导。
[解决办法]
这个需要结合 操作系统原理 汇编等来学习。
你可以进入程序调试模式,打开内存查看窗口,单步调试来试验。
[解决办法]
这个去找 PE 文件格式方面的资料来看, 知道了可执行文件的格式和它的加载过程, C 里面的东西如何对应应该是很自然就清楚了的. 不要局限在 C 里.
[解决办法]
推荐使用WinHex软件查看文件或内存中的原始字节内容。
《Windows PE权威指南》
[解决办法]
你学个汇编就知道了。
而且知道了详细情况用途也不大,因为堆、栈、程序区、静态数据的布局和管理是操作系统相关的,你换个系统可能就全不一样了。除非你想写操作系统,否则我认为知道有这么回事就够了。
[解决办法]
学点汇编不就全知道了……
另外,这是由编译器处理的,编程时不用考虑那么多。
如果你今后不做底层开发,个人感觉不需要知道那么多。
如果非要打破沙锅问到底,建议学习汇编。
[解决办法]
操作系统中的进程的内存分段:
1)代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的映像。代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作。
2)数据段:数据段用来存放程序静态分配的变量和全局变量,数据段分为一般数据段和BSS段,一般数据段即上面的.data段,用来存放已初始化全局变量。
3)BSS段:BSS段包含了程序中未初始化的全局变量,在内存中 bss段全部置零。
4)堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用C语言的malloc或C++的new等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用C语言的free或C++的delete等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
5)栈:栈是用户存放程序临时创建的局部变量,也就是说我们的花括号"{}"中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
[解决办法]
操作系统中一个进程的内存分段:
1)代码段:代码段是用来存放可执行文件的操作指令,也就是说是它是可执行程序在内存中的映像。代码段需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作。
2)数据段:数据段用来存放程序静态分配的变量和全局变量,数据段分为一般数据段和BSS段,一般数据段即上面的.data段,用来存放已初始化全局变量。
3)BSS段:BSS段包含了程序中未初始化的全局变量,在内存中 bss段全部置零。
4)堆(heap):堆是用于存放进程运行中被动态分配的内存段,它的大小并不固定,可动态扩张或缩减。当进程调用C语言的malloc或C++的new等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用C语言的free或C++的delete等函数释放内存时,被释放的内存从堆中被剔除(堆被缩减)。
5)栈:栈是用户存放程序临时创建的局部变量,也就是说我们的花括号"{}"中定义的变量(但不包括static声明的变量,static意味着在数据段中存放变量)。除此以外,在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值也会被存放回栈中。由于栈的先进先出特点,所以栈特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把堆栈看成一个寄存、交换临时数据的内存区。
[解决办法]
建议你看看<<深入理解计算机系统>>
不管我们怎么讲, 那都是我们自己的理解. 讲完了你还是不懂, 这种深入的话题还是自己多多看书.
[解决办法]
这个实在没有办法在论坛上讲清楚,这些问题的解释基本上涵盖了计算机学科的基础理论.
[解决办法]
你这是c++。我不懂。
给你点建议。
1、搞清楚COFF、PE、ELF等文件的结构,以及它们是如何被OS载入的。
2、搞清楚进程地址空间是怎么回事。
3、彻底搞清楚操作系统的内存分段和分页管理机制。
这里涉及的知识太多了。不是一句两句能说清楚的。
[解决办法]
#include <iostream>
using namespace std;
int a,b[5];//a和b在bss段,全局数据区
int add(int x,int y)//x,y在栈上,运行时分配空间,朝内存低地址方向生长,栈区stack
{
int c;//c在栈上
c=x+y;
return c;//返回局部变量的副本,不能返回指针
}
int main()
{
int d=2,e=3;//d、e在栈区,stack
int f=add(d,e);//f在栈上区
int *p = malloc(4);//p所指的空间在堆区,向高地址方向生长,heap
cout<<f<<endl;
}
建议楼主看看《深入理解计算机系统》
[解决办法]
a,b[]属于未经赋初值的全局变量,是bss区;
c局部变量,计算机存储在栈区,
传参过程中xy复制de的值但他们都属于局部变量,且未经const/static修饰,也是在栈区;
f同理,在栈区.
整个代码是只读的,存储在代码区.
一下代码楼主可以先判断下.
#include<stdio.h>
int a=0;//
int b;//
const int c=0;//
void fun(){
int x=0;
const int y=1;
static int z=3;
}
void main(){
int d;
int e=0;
const int f=0;
static int g=0;
char *arg ="ABCDE";
char str[10]="ABCDEF";
}
楼主可以自己分析,只要是绝对不可修改的,就可以认为是放在代码区的.像在局部代码中定义的const变量实际存放在栈区,只要骗过编译器,你是可以修改的动的.先写到这里,也算是对刚学的做下复习.学的那个比较全,但是具体忘记了
[解决办法]
MSDN98中的例子walker又名pwalk。完整列出指定进程的内存使用情况,显示进程地址空间内容,装载哪些DLL,代码、数据、堆栈段分配在何处,可以用来检测内存泄漏,监测内存使用。
http://download.csdn.net/detail/zhao4zhong1/3667896
[解决办法]
建议你看看<<深入理解计算机系统>> ++
[解决办法]
其实把堆和栈搞清楚了,对于编程来说应该就问题不大了。如果想深入进操作系统就要进一步去研究了。
[解决办法]
程序运行时候,操作系统给每个程序分配了4G(32位操作系统)的内存。可能程序用不到这么多,但是程序里面可以new,可以delete。
代码被编译成二进制之后,就没有代码之说了,都是几次识别的二进制序列,程序运行时候,被操作系统读到内存,存放在寄存器中,顺序执行。当然,我这里说顺序执行是错误的,因为有函数调用,会跳到其他的地址上,但是调用完成后,依然后返回调用的现场。
代码里面的变量,全局变量是在整个运行环境中都有效的变量,在你的程序中,int a,b[5], 和 int d,e具有相同的生命周期,在程序运行过程中都有效。这里请参考C++ primer中对于文件作用域的讲解。
函数调用时候,操作系统会做很多事情,保存现场,为形参分配空间,把实参值复制给形参,执行被调函数,返回现场。此处请参考操作系统中“中断”等概念。