c语言,内存分配情况想完全的搞清楚在运行一个程序的时候,内存是如何分配的,分配的多大的空间,顺序是怎么样
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中对于文件作用域的讲解。
函数调用时候,操作系统会做很多事情,保存现场,为形参分配空间,把实参值复制给形参,执行被调函数,返回现场。此处请参考操作系统中“中断”等概念。