C专家编程--读书笔记七 对内存的思考

第七章
 
一、知识点
1、作为80x86内存模型最基本的形式,8086中的段是一块64K的内存区域,由一个段寄存器所指向。内存地址的形成经过是:取得段寄存器的值,左移4位(相当于乘上16),或者换中思路,把段寄存器的值看成是20位的,也就是在值得右边扩充4个0。然后就是16位的偏移地址,它表示段内的地址。如果把段寄存器的值(经过移位)加上偏移地址,就得到最终的地址。不同的段地址加上偏移地址所形成的值可能指向同一个内存地址。(P146)
 
2、讨论数字概念时,需要注意所有的磁盘制造商都是使用十进制数而不是二进制数来表示的磁盘的容量。所以2GB的磁盘可以存储2000000000个字节的数据而不是2147483648个字节。(P148)
 
3、虚拟内存的基本思路是使用廉价但缓慢的磁盘来扩充快速但昂贵的内存。内存管理硬件负责把虚拟地址翻译为物理地址,并让一个进程始终运行于系统的真实内存中。应用程序程序员只看到虚拟地址,并不知道自己的进程在磁盘和内存之间来回切换。(P151)
 
4、虚拟内存通过“页”的形式组织。页就是操作系统在磁盘和内存之间移来移去或者进行保护的单位,一般为几K字节。进程只能操作位于物理内存中的页面。(P152)
 
5、Cache操作的速度与系统的周期时间相同,所以咯一个50MHZ的处理器,其Cache的存取周期为20ns。内存读取的数据以行为单位i,在读取的同时也装入到Cache中。(P154)
 
6、Cache的组成:
 

8、堆区域用于动态分配的存储,也就是通过malloc(内存分配)函数获得的内存,并通过指针访问。堆中的所有东西都是匿名的——不能按名字直接访问,只能通过指针间接访问。从堆中获取内存的唯一办法就是通过调用malloc库函数。(P157)
 
9、每次当调用malloc分配内存时,注意在以后调用相应的free来释放它。一种简单的方法防止内存泄露就是在可能的时候使用alloca()来分配动态内存,当离开调用alloca()的函数时,它所分配的内存会被自动释放。(P159)
 
10、检测内存泄露的步骤:(P159)
(1)、首先使用swap命令观察还有多少可用的交换空间:
/usr/sbin/swap -s
在一两分钟内键入该命令三到四次,看看可用的交换区是否在减少。如果发现不断有内存被分配且从不释放,一个可能的解释就是有个进程出现了内存泄露。
(2)、确定可疑的进程,看看它是否该为内存泄露负责。你可能已经知道哪个进程是罪魁祸首,不然可以实用“pa -lu用户名”命令来显示所有进程的大小。同样数次重复这个命令,可疑发现任何动态分配内存的进程的大小都在增长。
 
11、总线错误几乎都是由于未对齐的读或写引起的。它之所以称为总线错误,是因为出现未对齐的内存访问请求时,被堵塞的组件就是地址总线。对齐(alignment)的意思就是数据项只能存储在地址时数据项大小的整数倍的内存位置上。(P163)
 
12、段错误(segmentation violation)通常是由于内存管理单元(负责支持虚拟内存的硬件)的异常所致,而该异常则通常是由于解除引用一个未初始化或非法值的指针引起的。(P164)
 
13、通常导致段错误的几个直接原因:(P166)
(1)、解除引用一个包含非法值的指针;
(2)、解除引用一个空指针(常常由于从系统程序中返回空指针,并未经检查就使用);
(3)、在未得到正确的权限时进行访问。例如,试图往一个只读的文本段存储值就会引起段错误。
(4)、用完了堆栈或者堆空间。
在绝大多数情况下,总线错误意味着CPU对进程引用内存的一些做法不满,而段错误则是MMU对进程引用内存的一些情况发出抱怨。
 
14、最终可能导致段错误的常见编程错误是:(P166)
(1)、坏指针值错误:在指针赋值之前就用它来引用内存,或者向库函数传送一个坏指针,或者对指针继续拧释放之后再访问它的内容。
(2)、改写错误:越过数组边界写入数据,在动态分配的内存两端之外写入数据,或改写一些堆管理数据结构。
(3)、指针释放引起的错误:释放同一个内存块两次,或者释放一块未曾使用malloc分配的内存,或释放仍在使用中的内存,或释放一个无效的指针。
 
二、问题
1、alloca()函数?(P159)
 
2、在PC上编写一个捕捉INT 1B(Ctrl-Break)信号的信号处理程序,让它打印一条友好的用户信息但并不退出程序。(P163)
 
3、编写一个信号处理程序来捕捉总线错误和段错误信号,让它们打印一条对用户更为友好的信息,然后退出。(P165)
posted on 2012-04-30 23:20  谷堆旁边  阅读(382)  评论(0编辑  收藏  举报