一:什么是段:
(1)在UNIX中,段就是一块以二进制形式出现的相关内容
(2)在内存模型中,段是内存模型设计的结果,分割为64KB为单位的区域,每个这样的区域是段
内存地址的形成过程是:取得段寄存器的值,左移4位(不同的段地址加上偏移地址可能是指向同一个内存地址的)
2:虚拟地址
操作系统负责具体细节,使得每个进程都以为自己拥有整个地址空间的独家访问权。这个就是通过“虚拟地址”来实现的。所有的进程共享机器的无力内存,当内存用完时候就用磁盘保存数据,在进程运行中,数据与磁盘和内存之间来回移动,内存管理硬件负责把虚拟地址翻译为无力地址,并让一个进程始终运行于系统的真正内存中,应用程序程序员只看到虚拟地址,并不知道自己的进程在磁盘和内存之间的来回切换。
虚拟内存通过“页”的形式组织。当内存的映像在磁盘和内存来回移动时候,称他们是page in,page out.
与进程有关的所有内存都被系统所使用,如果改进成不会马上运行,操作系统可以暂时取回所有分配给他的物理内存资源,让该进程所有相关信息都备份到磁盘上。磁盘上有一个特殊的“交换区”,用于保存从内存患处的进程。
进程只能操作位于物理内存中的页面
3:Cache存储器
当数据从内存读入时候,“整行”的数据被装入Cache,如果程序具有良好的地址引用局部性,那么CPU以后对临近数据的引用就直接从快速Cache中读取,而不用缓慢的从内存中读取。Cache操作的速度与系统的周期时间是一致的。
Cache包含一个地址的列表以及他们的内容。“内存读取的数据是以行为单位,在读取的同时也装入到Cache中”
行:就是对Cache进行访问的单位
块:一个Cache行内的数据被称作块。
Cache:一个Cache由许多行组成,有时候也使用相关的硬件来加速。
4:数据段和堆
堆栈段能够自动增长,数据段也包含一个对象,用于完成这项工作-->堆。堆区域用于动态分配的存储,也就是通过malloc函数获得的内存,并通过指针访问。堆中的所有东西都是匿名的,不能按照名字直接访问,只能通过指针间接访问。
从堆中获取内存的唯一办法就是通过调用malloc库函数。
堆内存的回收不许要与分配的顺序一致。
5:内存泄漏
堆经常会出现两种类型的问题:
(1)释放或者改写仍在使用的内存(内存损坏)
每当调用malloc分配内存时候,都需要调用free来释放。
(2)未释放不再使用的内存(内存泄漏)
错误就是操作系统所检测出来的异常
6:总线错误与段错误:
当硬件告诉操作系统一个有问题的内存引用时候,就会出现这两种错误。操作系统通过向出错的进程发送一个信号与之交流。而信号就是一种事情通知或一个软件中断。
1:总线错误
事实上,总线错误几乎都是由于未对齐的读或者写引起的。对齐的意思就是数据项只能存储在地址是数据项大小的整数倍的内存位置上。“数据项不能跨越页面或者Cache边界”
eg:访问一个8字节的double数据时候,地址只允许是8的证书倍,所以一个double数据可以存储于地址24,8008或者32768,但是不能存储于地址1006(无法被8整除)
2:段错误
段错误是由于内存管理单元的异常所致,而该异常通常是由于接触引用一个未初始化或者非法值的指针引起。如果指针引用一个并不位于你的地址空间中的地址,操作系统便回对此进行干涉。
eg:
int *p=0;
*p=17//导致指针具有非法的值通常是由于不同的编程错误所引起的,和总线错误不同,
段错误更像是一个间接的症状而不是原因。
总线错误意味着CPU对进程引用内存的一些做法不满,而段错误则是MMU对进程引用内存的一些情况发出的抱怨。
导致段错误的直接原因:
(1)解除引用一个包含非法值的指针
(2)解除引用一个空指针
(3)在未得到正确的权限时候进行访问.eg:向一个只读文件中写入数据
(4)用完了堆栈或者堆空间。
导致段错误的编程错误:
(1)坏指针值错误:在指针赋值之前就用它来引用内存,或者向库函数传送一个坏指针,第三种产生坏指针的原因是对指针进行释放以后再访问它的内容
eg:free(p); p=NULL;
(2)改写错误:越过数组边界写入数据,在动态分配内存两端之外写入数据
(3)指针释放引起错误:释放同一个内存快两次,或者释放一块从未使用malloc分配的内存
eg:
for(p=start;p;p=p->next)//这样的循环中迭代一个链表,并在循环体中使用free(p)这样,在下一次循环中,程序就会对已经释放的指针进行解除引用操作,从而导致错误
修改:
for(p=start;p;p=tmp)
{
tmp=p->next;
free(p);
}
阅读(1392) | 评论(0) | 转发(0) |