一:栈(stack)
函数调用之前会将当前存入到栈中。程序中栈是由编译器管理。
入栈,栈指针减小
出栈,栈指针增大
栈遵守先入后出原则
栈只有唯一入口,即栈指针。而堆可以有多个入口。
在函数中,参数和自动变量都将送入栈区。
函数退出后,属于该函数的栈自动释放,此时该栈里的内容不能被别的函数使用,
即内层函数可以使用外层函数的栈内存,但外层函数不能使用内层函数的栈内存。
实践解决问题
之前要实现将PC机的较大的图像文件写nand flash中,采用main函数设立一个数组变量,将PC机的.bmp图像fread读入,失败,就是因为栈设定太小,无法分配。之后采用全局变量才解决,当时还不知道是这个原因。
二 堆(heap):
堆内存区域的分配和释放时通过调用库函数来完成的,由程序员分配和释放,他们的使用需要包含标准库文件
#include<stdlib.h>
实现内存分配的核释放的4个主要函数:
Void *malloc(size_t size);
Void free(void *ptr)
Void *calloc(size_t nmemb, size_t size) 与malloc不同的是,会把内容初始化为0;
Void *realloc(void* ptr, size_t size) 是malloc 和 free的结合
当ptr=NULL时,相当于malloc, 此时不初始化为0
当size = 0 时,相当于free
当size小于原来分配的大小,ptr不变,重合部分内存不变,多余部分释放
当size 大于原来分配的大小,ptr可能变化,
若原分配内存区域后面是未分配的空间,则不需要移动内存指针,即ptr不变,重合部分内存不变,多余部分为不确定数
若原分配内存区域后面为有足够空间,则需要移动内存指针,按照新内存大小,重新分配一块内存空间,将原有内存中的内容,复制到新的内存空间中,释放原有看内存空间。
参考文献:嵌入式Linux上的C语言编程实践 韩超,魏治宇 电子工业出版社
三:全局区(静态区static):
包含只读数据段,读写数据段,未初始化数据段。
四:文字常量区
五:程序代码区
六:比较
这是一个前辈写的,非常详细
//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"优化成一个地方。
堆具有灵活性,何时分配,释放的逻辑完全由编程人员决定。但是存在风险,如1:开辟内存未及时释放,造成内存泄露,2:野指针的存在,内存已经释放,但该指针仍被使用,正确的做法是一旦该指针指向的内存一旦释放,就将该指针赋值为NULL。在使用某指针时,首先判断该指针是否是NULL
3:非法释放指针,未给指针分配内存就释放。
总之又果必有因,只有作为malloc(),calloc()或realloc()返回值的指针,才可以被free()释放和被realloc()处理。
栈的存取速度比较快。但使用不够灵活。
这些都是辩证的,需要编程人员合理的选择利用堆栈,从使用的角度,一般来说,栈内存更适用于容量较小的单个变量(如C语言的基本变量类型,较小的结构体和数组),而堆内存适用于开辟较大的块内存。