- 日期:20160614
- 作者:i.sshe
- https://github.com/isshe
【初探】内存管理知多少?
1. 基础问题
- 1.1 常见的内存管理方式有哪些?
- 1.2 什么是虚拟内存?
- 1.3 什么内存泄漏?如何检测?如何避免?
- 1.4 什么是内存溢出?
2. 拓展问题
- 2.1 什么是段错误?
- 2.2 什么是碎片?什么是外碎片?什么是内碎片?
- 2.3 什么是ELF?
- 2.4 如何知道系统中进程能分配多大的内存?
- 2.5 什么是动态链接?什么是静态链接?
3. 基础问题解答
3.1 常见的内存管理方式有哪些?
- 页式管理:将一个进程的逻辑地址空间划分成若干个大小相等的部分,每个部分称为页。
- 优点:
- 没有外碎片,内碎片不大于一页。
- 缺点:
- 程序全部装入内存;
- 要求相应的硬件支持。
- 优点:
- 段式管理:
- 把程序按内容或过程函数关系分段,每个段有自己的名字。
- 优点:
- 可以根据不同的段采用不同的保护;
- 可以以段为单位进行共享;
- 可以分别编写和编译;
- 缺点:
- 会产生碎片;
- 段页式管理:
- 主存分段,段内再分页。
- 内存分配时,是以页为单位。
- 每取一次数据都要访问3次内存。
- 优点:
- 内存利用率更高;
- 以上种管理方式的优点都有;
- 缺点:
- 需要硬件支持;
- 占用内存更多;
- 执行速度有所下降;
3.2 什么是虚拟内存?
- 基本思路: 用廉价、缓慢的磁盘来扩充快速、昂贵的内存。
- 程序使用的虚拟内存中的内容就被载入物理内存,物理内存中一段时间不用的数据,会被移动到磁盘,省下的物理内存用于其他地方。
- 优点:
- 扩大地址空间;
- 内存保护。每个进程运行在各自的虚拟内存中,互不干扰。
- 内存分配公平。每个进程都可以得到同样大小的虚拟内存。
- 进程通信可采用虚拟共享的方式。
缺点: - 虚拟内存的管理需要各种数据结构,需要额外的内存。
- 虚拟地址和物理地址的转换需要时间。
- 数据的换入换出需要磁盘I/O,需要大量时间。
3.3 什么内存泄漏?如何检测?如何避免?
- 内存泄漏:未释放不再使用的内存。
- 内存泄漏是最难调试发现的问题之一。
- 检测方法:
- 方法一:
- 使用命令swap(或其他netstat、vmstat)观察是否有内存泄漏。(1~2分钟内执行5次左右)
- 确定可疑进程。(可使用ps命令查看进程大小,多次执行,观察内存增长的进程)
- 方法一:
- 避免方法:
- 调用malloc()分配内存后,注意用对应的free()释放内存。
- 必要时,使用alloca()分配动态内存:当离开调用alloca()的函数时,内存会被释放。
3.4 什么是内存溢出?
- 内存溢出(out of memory):是指程序在申请内存时,没有足够的内存空间供其使用。例如C语言中声明int类型,赋值long型就有可能会溢出。
4. 拓展问题解答
4.1 什么是段错误?
段错误(segmentation fault(core dumped))
产生原因:
解引用一个未初始化或非法值的指针。(p是指针,*p即为解引用)
int *p = null; *p = 22;
解引用一个空指针。
- 未得到正确权限时进行访问。(如:写只读的文本段)
- 堆或栈空间耗尽。
越界访问:
p = malloc(10); p[10] = 10;
同一内存释放两次;
- 释放不是malloc分配的内存;
- 释放使用中的内存;
4.2 什么是碎片?什么是外碎片?什么是内碎片??
- 碎片:由于内存分配造成的小空隙的无法被使用的内存。
- 内碎片:分配给某程序的内存空间,程序不使用,但系统也无法再利用(直到程序结束)。
- 外碎片:空间太小,无法分配给任何的进程,这些小空间即外碎片。
4.3 什么是ELF?
- 目标文件和可执行文件可以有几种不同的格式,ELF是其中一种(绝大多数SVr4系统中采用)。【BSD UNIX中是:a.out格式】
- ELF:原意为“Extensible Linker Format, 可拓展链接器格式”,现在表示为“Executable and Linking Format, 可执行文件和链接格式”
4.4 如何知道系统中进程能分配多大的内存?
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int mb=0;
while(malloc(1<<20)) //1<<20可以改其他。
{
mb++;
}
printf("mb = %d\n", mb);
return 0;
}
4.5 什么是动态链接?什么是静态链接?
- 静态链接:函数库的一份拷贝是可执行文件的一部分。(并不是整个函数库,只是需要的函数!)
- 动态链接:运行时载入所需函数库。(可执行文件只包含文件名,运行时载入器根据文件名找到函数库)
- 优点:
- 可执行文件体积小;
- 能更有效地利用磁盘空间;
- 函数库升级更容易;
- 缺点:
- 运行速度稍慢;
- 优点:
- linux下动态链接后缀为.so, 静态链接后缀为.a;
- -l 选项链接函数库;
- -L 选项指定目录;
- 静态链接时要注意顺序的问题,否则会遇到各种“未定义”;(被调用的写后面,调用的写前面)
5. 参考资料
-
- 《C专家编程》
-
- 《计算机操作系统》