
1. 初步了解-程序内存分配
C / C ++编译程序占用的内存分为以下几部分
(从上到下,从高内存地址到低内存地址)
1. 堆栈区域(堆栈)由编译器自动分配和释放,用于存储函数参数值,局部变量值等. 其操作类似于数据结构中的堆栈.
2. 堆-通常由程序员分配和释放,如果程序员不释放它,则在程序结束时OS可能会回收它. 请注意,它与数据结构中的堆不同,并且分配方法类似于链表,哈哈.
3. 全局区域(静态区域)(静态)-全局变量和静态变量的存储放在一起,已初始化的全局变量和静态变量在一个区域中,未初始化的全局变量和未初始化的静态变量在另一个相邻区域中. -程序结束后由系统释放.
4. 文本常量区域常量字符串放置在此处. 程序结束后由系统释放
5. 程序代码区-用于存储函数体的二进制代码.
第二个示例程序
//main.cpp
int a = 0; 全局初始化区
char *p1; 全局未初始化区
main()
{
int b; 栈
char s[] = "abc"; //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"
优化成一个地方。
}
三,堆和栈的理论知识

2.1如何申请
堆栈:
由系统自动分配.
例如,在函数中声明一个局部变量int b;系统会自动为堆栈中的b腾出空间
堆:
需要自己申请程序员,并在c中指定大小,malloc函数
例如p1 =(char *)malloc(10);
在C ++中使用new运算符
例如p2 = new char [10];
但是请注意,p1和p2在堆栈中.
2.2申请后的系统响应

堆栈: 只要堆栈的剩余空间大于请求的空间,系统就会为程序提供内存,否则将报告异常以指示堆栈溢出.
堆: 首先,您应该知道操作系统有一个记录空闲内存地址的链表. 当系统收到程序的应用程序时,它将遍历链接列表以查找第一个堆节点,该第一个堆节点的空间大于请求的空间,然后从可用节点列表中删除该节点,并删除该节点的空间被分配给程序. 此外,对于大多数系统,此分配的大小将记录在此存储空间的第一个地址处. 这样,在代码中的delete语句可以正确释放内存空间.
此外,由于找到的堆节点的大小可能不完全等于应用程序的大小,因此系统会自动将多余的部分放入空闲列表中.
2.3应用程序大小限制
堆栈: 在Windows中,堆栈是一个扩展到低位地址的数据结构,并且是一个连续的内存区域. 这句话意味着堆栈顶部的地址和堆栈的最大容量是由系统预先定义的. 在WINDOWS下,堆栈的大小为2M(有人说是1M,简而言之,它是在编译时确定的常数). 当请求的空间超过堆栈的剩余空间时,将提示溢出. 因此,堆栈中可用的空间较小.
堆: 堆是一种扩展到高地址的数据结构,并且是一个不连续的内存区域. 这是因为系统使用链接列表存储自然不连续的空闲内存地址,并且链接列表的遍历方向是从低地址到高地址. 堆的大小受计算机系统中有效虚拟内存的限制. 可以看出,堆获得的空间更加灵活,更大.
2.4应用效率比较:
系统自动分配堆栈,速度更快. 但是程序员无法控制它.
堆是new分配的内存,通常速度较慢并且容易出现内存碎片,但是使用起来最方便. 另外,在WINDOWS下,最好的方法是使用VirtualAlloc分配内存. 它不在堆中. 虽然它使用起来最不方便,但它不在堆栈上,而是直接在进程的地址空间中保留一块内存. 但是它既快速又灵活.
2.5在堆和堆栈中存储内容:
堆栈: 调用一个函数时,第一个要压入堆栈的是主函数之后的下一条指令(函数调用语句的下一个可执行语句)的地址,然后是该函数的参数. 在大多数C编译器中,参数是从右到左压入堆栈,然后是函数中的局部变量. 请注意,静态变量未堆叠. 当该函数调用结束时,局部变量首先从堆栈中弹出,然后是参数. 最后,堆栈顶部的指针指向初始地址,该地址是主函数中的下一条指令,程序从此点继续执行.

堆: 通常,一个字节用于在堆的开头存储堆的大小. 堆中的特定内容由程序员安排.
2.5在堆和堆栈中存储内容:
char s1 [] =“ aaaaaaaaaaaaaaaaa”;
char * s2 =“ bbbbbbbbbbbbbbbbbb”;
aaaaaaaaaaaaa在运行时分配;
bbbbbbbbbbb是在编译时确定的;
但是,在后续访问中,堆栈上的数组比指针所指向的字符串(例如堆)要快.
例如:
#include
void main()
{
char a = 1;
char c[] = "1234567890";
char *p ="1234567890";
a = c[1];
a = p[1];
return;
}
相应的汇编代码
10: a = c [1];

00401067 8A 4D F1 mov cl,byte ptr [ebp-0Fh]
0040106A 88 4D FC mov字节ptr [ebp-4],cl
11: a = p [1];
0040106D 8B 55 EC mov edx,dword ptr [ebp-14h]
00401070 8A 42 01 mov,byte ptr [edx + 1]
00401073 88 45 FC mov字节ptr [ebp-4],al
第一种类型在读取时将字符串中的元素直接读取到寄存器cl中,而第二种类型则要求先读取指针值
在edx中,根据edx读取字符显然很慢.
2.7摘要:
堆和栈之间的区别可以通过以下隐喻看出:
使用堆栈就像去餐厅吃饭. 只需点餐(发出申请),付款和用餐(使用),然后在吃饱的时候离开即可. 您不必担心切菜,洗碗和洗碗等准备工作. 刷锅和其他修整工作的优点是速度快,但自由度小.
使用堆就像制作自己喜欢的菜肴. 这比较麻烦,但是更符合您自己的口味,并且具有很大的自由度. (经典!)
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/shoujiruanjian/article-292171-1.html
我相信
难道我做出的产品会把不合格的送去质检局检测