12.内存分区说明
1.程序编译过程
编译过程又可以分成两个阶段:编译和汇编。
编译:
编译是读取源程序(字符流),对之进行语法分析,将高级语言指令转换为功能等效的汇编代码,
编译过程包括两个主要阶段:编译预处理和编译、优化
编译预处理:
(1).宏定义指令替换(宏定义展开)
(2).条件编译指令,
(3).头文件包含指令(头文件展开);注释不被处理
编译、优化阶段:
经过预编译得到的输出文件中,只有常量;如数字、字符串、变量的定义
汇编:
汇编过程实际上指把汇编语言代码翻译成目标机器指令的过程。
(1).text(代码区):只读,函数,包含了操作系统和应用程序的所有代码;
(2).data区(数据区):初始化的数据,全局变量,static变量,文字常量(只读);
(3).bss区(bss段):没有初始化的数据,全局变量,static变量;
(4).stack(栈区):普通局部变量,自动管理内存,先进后出;
(5).heap(堆区):手动申请空间,整个程序结束,系统也会自动回收。
2.栈越界
函数递归,容易导致栈越界,出现段错误
3.memset()
void *memset(void *s,int c,size_t n);
清空内存,填充字符;
4.memcopy()
void *memcopy(void *s, int c,size_t n);
n拷贝内存的总大小;使用memcopy()要考虑内存重叠,最好使用memmove();
5.memcmp()
int memcmp(const void *buf1, const void *buf2, unsigned int count);
比较两个数据是否相等,大小;
比较内存区域buf1和buf2的前count个字节。
6.堆区内存分配与释放
int *p; *p = 10; printf("*p = %d\n", *p); //野指针,出现段错误
解决:
a.在栈区申请一个空间,指针指向这个空间;
b.在堆区申请一个空间(malloc(),头文件:#include<stdlib.h>),指针指向这个空间;
7.malloc()
a.参数是指定的堆区分配多大的空间;
b.返回值:成功就是堆区空间的首元素地址;
c.失败返回NULL;
int *p; p = (int *)malloc(sizeof(int));
d.使用free()释放,不是释放变量,而是释放p所指向的内存,释放是指系统回收了,如果再用就是非法操作内存;
8.内存泄漏
动态分配空间,不释放。
9.内存污染
操作野指针所指向的内存,堆栈越界。
10.指针指向内存空间释放
只能释放一次,每次释放前先判断是否为空:
11.返回栈区地址
操作非法内存,段错误;
fun()的变量存储在栈区,调用完就释放了,后面再操作就是非法操作;
12.值传递
正常,p只是作为形参