您的位置:首页 > 其它

【初探】内存管理知多少

2016-06-14 18:05 239 查看
日期: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专家编程》

《计算机操作系统》
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息