1、Intel 80X86系列处理器的发展历程
4008 —> 8008 —> 8080 —> 8085 —> 8086 —> 80186 —> 80286 —> 80386 —> 80486 —> Pentium 32
2、内存模型以及它的工作原理
段的含义:一块64KB的内存区域,有一个段寄存器所指向。
内存地址的形成:取得寄存器的值,左移4位(相当于乘以16,左乘右除),或者把段寄存器值看成20位,在值得右边扩充4个0,然后段寄存器值加上偏移的16位地址,得到最终的值。
3、虚拟内存
概念:只是对多层存储进行扩充,使用磁盘而不是主存来保存运行进程的映像。
虚拟内存通过“页的形式组织。页就是操作系统在磁盘和内存之间移来移去或进行保护的单位。,一般为几K字节。
进程只能操作位于物理内存的页面中。
4、Cache存储器
Cache位于CPU和内存之间,是一种极快的存储缓冲区,是多层存储概念的更深扩展。
Cache包含一个地址的列表以及他们的内容。
5、数据段和堆
数据段能够根据需要自动增长的包含了一个对象,这个对象就是堆。
堆区域用于动态分配的存储且堆中的所有东西都是匿名的,不能按名字直接分配,只能通过指针间接访问。
对内存的回收不必与他所分配的顺序一致。
堆的末端由一个称为break的指针来标识,但堆管理器需要更多的内存时,它可以通过系统调用brk和sbrk来移动break指针。
内存管理的调用:malloc和free:从堆中获得内存以及吧内存返回给堆。brk和sbrk:调整数据段的大小至一个绝对值(通过某个增量)。
6、内存泄漏
堆常会产生两种内存的问题:释放或改写正在使用的内存(称为内存毁坏);未释放不再使用的内存(称为内存泄漏)。
避免内存泄漏:每次调用malloc函数时,在以后都要调用相应的free来释放它。
使用alloca来分配动态内存,当离开调用的alloca的函数时,他所分配的内存会自动释放。
泄露的内存往往比忘记释放的数据更大。
检测内存泄漏的方法:使用swap命令来观察还有多少可用的交换空间,用“ps-lu用户名”命令来显示所有进程的大小,确定可疑的进程。
7、总线错误和段错误
总线错误和段错误在不同的操作系统版本上各有不同。
总线错误:总线错误几乎都是由于未对齐的读或写引起的。
对齐:数据项只能存储在地址是数据项大小的整数倍的内存位置上。编译器通过自动分配和填充数据来进行对齐。
8、段错误
段错误是由内存管理单元的异常所引起的,该异常通常由于解除引用一个未初始化或非法值的和指针引起的。
如果未初始化的指针恰好具有未对齐的值,他将产生总线错误,而不是段错误。
导致段错误的原因
A、解除引用一个包含非法值的指针。
B、解除引用一个空指针(常常由于从系统程序中返回空指针,并未检查就引用)。
C、在未得到正确的权限是进行访问。(例如试图往一个只读的文本段存储值)
D、用完了堆栈或堆空间。
9、可能导致段错误的常见编程错误
坏指针值错误。
在指针赋值之前就用它来引用内存。
向库函数传送一个坏指针。
对指针释放之后在访问它的内容。
改写错误
越过数组边界写入数据。
在动态分配的内存两端之外写入数据。
改写一些堆管理数据结构。(在动态分配的内存之前的区域写入数据)
指针释放引起的错误
释放同一个内存块两次。
释放一块未曾使用malloc分配的内存。
释放乃在使用中的内存。
释放一个无效指针。