内存管理技术
1.内存管理技术
1.1存放常量字符的指针和数组的问题(非常重要)
- 如:
char* str = “hello”;
char strs[] = “hello”;- 对于一个记录常量字符常的字符指针来说,指针指向的内容不可以改变,指针指向可以改变
- 对于一个记录常量字符串的字符数组来说,指针指向的内容可以改变,指针的指向不可以改变
- 对于一个记录动态内存的字符指针来说,指针指向的内容和指针的指向都可以改变
1.2虚拟内存管理技术(尽量理解)
- 在linux系统中,一般都是采用虚拟内存管理技术来进行内存空间的管理,即:每个进程都可以有0~4G-1的地址空间(虚拟的,并不是真实存在的,)由操作系负责建立虚拟地址到真实物理内存/文件的映射,因此不同进程中的虚拟地址看起来是不一样的,但是所对应的真实物理内存/文件是不一样的;
其中0~3G-1之间的地址空间叫做用户空间,而3G~4G-1之间的地址空间叫做内核空间,一般用户程序都运行在用户空间,不能
直接访问内存空间,但是操作系统的内存提供相关的API函数可以访问内核空间
内存地址的基本单位是字节,而内存映射的基本单位是内存页,目前主流的操作系统中一个内存页的大小是4kb(4096个字节)
1Tb = 1024Gb
1Gb = 1024Mb
1Mb = 1024Kb
1Kb = 1024byte(字节)
1byte = 8个bit(二进制位)
1.3 段错误的由来
(1)试图操作没有操作权限的内存空间时可能引发段错误
- 如:修改只读常量区中的数据
(2)试图操作没有经过映射的虚拟地址时可能引发段错误
- 如:赋值任意一个虚拟地址进行赋值
1.4 使用malloc函数申请动态内存
(1)使用malloc函数申请动态内存时的注意事项(重点)
使用malloc函数申请动态内存时,除了申请参数指定的内存空间之外,可能会申请额外的12个字节(一般原则)用于存放该动态内存的大小、是否可用等管理信息;
切记不要对malloc函数申请的动态内存进行越界赋值等操作,因为一旦不小心破坏动态内存的管理信息是,可能引发段错误等等;
(2)使用malloc函数申请动态内存时的一般性原则(了解)
- 一般来说,使用malloc函数申请比较小块的动态内存时,操作系统一般会一次性映射33个内存页,用于提高效率;
#include<stdio.h>
#include<unistd.h>
#include<sys/types.h>
getpid() - 用于获取当前进程的编号
- cat/proc/进程号/maps - 用于查看指定进程的内存映射情况,具体结果有刘列:地址范围、访问权限、偏移量、设备的编号、i节点的编号、进程名称等着;
- 其中要求大家关注:heap区
1.5 使用free函数释放动态内存的一般性原则(了解)
- 一般来说使用free函数释放动态内存时,释放多少,则映射的总量中减去多少,当所有的动态内存都释放完毕后,操作系统依然会保留33个
内存页,用于提高效率;
1.6 内存管理的相关函数
(1)getpagesize函数
#include <unistd.h>
int getpagesize(void);
主要用于获取当前系统中一个内存页的大小并返回;
(2)sbrk函数
#include <unistd.h>
void *sbrk(intptr_t increment);
函数功能:
主要功能用于调整动态内存的大小,具体调整方式如下:
当 increment > 0时, 表示增加/申请动态内存;
当 incremnet = 0时,表示获取当前动态内存的末尾地址;
当 increment < 0时,表示减小/释放动态内存;
无论是增加、减少还是获取操作,当函数调用成功时都会返回调整之前的动态内存末尾地址,失败返回(void*)-1;
注意:
- 一般来说,使用sbrk函数申请比较小的动态内存时,系统一般会映射一个内存页大小的内存空间,当申请的动态内存超过一个内存页时,
系统会再次映射一个内存页,当释放完毕所有的动态内存时,系统不会保留任何的内存映射;- 与malloc()/free()函数相比,sbrk()函数更节省内存空间,但是效率没有melloc()/free()函数那么高;
- 虽然sbrk函数既能申请内存又能释放内存,但是申请内存空间更佳,所有一般只用sbrk函数申请内存;
练习:
a.自定义函数,获取参数传入文件的大小并返回,如果打开文件失败则返回错误;(错误处理,标c中文件处理)
b.查询并尝试使用brk函数;