1 在Unix操作系统中,段(segment)是一块以二进制出现的相关内容。
在Intel80X86内存模型中,段是内存模型设计的结果,在80X86内存模型结构中,各处理器的地址空间不一致(为了保持兼容性),因此它们被分割成以64K为基本单位的区域,每个这样的区域称为段。
8086中的段是一块64K的内存区域,由一个段寄存器指向。
内存地址的形成过程是:段寄存器的值左移4位+16位的偏移地址=20位的内存地址
Note:不同的段地址加上偏移地址有可能指向同一块内存地址
2 虚拟内存:
其基本思路是用廉价但缓慢的硬盘来扩充快速且昂贵的内存。在任一给订的的时刻,程序实际需要使用的虚拟内存使用区段就被载入物理内存中。当物理内存中的一部分数据长时间不用,它们就可能被转移到硬盘中,节省下来的物理内存用来载入需要使用的其他数据。
虚拟内存通过页的形式组织。页就是操作系统在 硬盘和内存之间移来移去或进行数据保护的单位,一般为几KB。
从潜在的可能性上讲,与进程有关的所有内存都将被系统使用。如果该进程不会马上被执行(可能它的优先级比较低或者处于睡眠状态),操作系统可以暂时取回分配给它的所有内存资源,并将该进程所有相关信息都备份到磁盘上。这样,这个进程就被“换出”,在磁盘中由一个特殊的交换区用来保存被“换出”的进程,交换区的大小一般为物理内存的几倍。只有用户进程才能被换进换出,内核进程常驻内存中。
进程只能操作位于物理内存中的页面。当进程引用一个不存在于物理内存中的页面时,MMU(内存管理单元)会产生一个页错误。内核对此事件作出响应,并判断引用是否有效。如果无效,内核向进程发出一个“segmentation violation”(段违规)的信号。如果有效,内核从磁盘中取出该页换入到内存中。一旦页面进入内存,进程便被解锁可以重新运行。
3 段错误
导致段错误的几个原因:
(1)解除引用一个包含非法值的指针
(2)解除引用一个空指针(通常由于从系统程序中返回的空指针并未经检查就使用)
(3)在未得到正确的授权时进行访问,例如修改只读文件
(4)用完了堆栈或堆空间(虚拟内存虽然巨大但并不是无限大)
导致段错误的几个编程错误:
(1)坏指针值错误:
在指针赋值之前就用它来引用内存;向库函数传递一个坏指针;对指针释放之后又访问它的内容
(2)改写错误:
写数据时超过了数组容量;在动态分配的内存的两端写入数据;改写一些堆管理的数据结构
(3)指针释放错误:
两次释放同一块内存;释放一块未从使用Malloc分配的内存;释放仍在使用的内存;释放一个无效的空指针
一个极为常见的与释放内存相关的错误就是在for(p=start;p;p=p->next)这样的循环中迭代一个链表,并在循环体中使用free(p),这样在下一次迭代循环时,会对已经释放的指针p进行解除引用操作,从而导致不可预料的错误。
解决的方法:引用一个临时的变量存放下一个元素的地址
struct nod *p,*start,*tmp; for(p=start;p;p=tmp){ tmp=p->next; free(p) }
|
阅读(1262) | 评论(0) | 转发(0) |