C专家编程--读书笔记六 运行时数据结构

第六章
 
一、知识点
1、代码和数据的区别也可以认为是编译时和运行时的分界线。编译器的绝大部分工作都跟翻译代码有关;必要的数据存储管理的绝大部分都在运行时进行。(P121)
 
2、"a.out"是“assembler output(汇编程序输出)”的缩写形式。(P121)
 
3、就目标文件而言,段(segments)是二进制文件中简单的区域,里面保存了和某种特定类型(如符号表条目)相关的所有信息。一个段一般包含几个section。段表示一个二进制文件相关的内容块。(P122)
 
4、一个可执行文件一般包含三个段:文本段、数据段、bss段(由符号开始的块)。BSS段只保存没有值得变量,所以事实上它并不需要保存这些变量的映像。运行时需要的BSS段的大小记录在目标文件中,但BSS段(不像其他段)并不占据目标文件的任何空间。a.out以段的形式组织。(P124)
 
5、段可以方便地映射到连接器在运行时可以直接载入的对象中!载入器只是取文件中每个段的映像,并直接将它们放入内存中。从本质上说,段在正在执行的程序中是一块内存区域,每个区域都有特定的目的。(P125)
 
6、文本段包含程序的指令;数据段包含经过初始化的全局和静态变量以及它们的值;BSS段的大小从可执行文件中得到,然后连接器得到这个大小的内存块,紧跟在数据段之后。包含数据段和BSS段的整个区段通常统称为数据区。这是因为在操作系统的内存管理术语中,段就是一片连续的虚拟地址,所以相邻的段被结合。一般情况下,在任何进程中数据段是最大的段。堆栈段用于保存局部变量、临时数据、传递到函数中的参数等。同时,我们还需要堆空间,用于动态分配的内存。虚拟地址空间的最低部分未被映射。也就是说,它位于进程的地址空间内,但并未赋予物理地址,所以任何对它的引用都是非法的。在典型情况下,它是从地址零开始的几K字节。它用于捕捉使用空指针和小整型值得指针引用内存的情况。(P125)
 
7、堆栈段有三个主要的用途,其中两个跟函数有关,另一个跟表达式计算有关:(P127)
(1)、堆栈为函数内部声明的局部变量提供存储空间。按照C语言的术语,这些变量被称为“自动变量”。
(2)、进行函数调用时,堆栈存储于此有关的一些维护性信息。这些信息被称为堆栈结构,另外一个更常用的名字是过程活动记录。它包括函数调用地址(即当调用的函数结束后调回的地方)、任何不适合装入寄存器的参数以及一些寄存器值的保存。
(3)、堆栈也可以被用作暂时存储区。
除了递归调用之外,堆栈并非必须。因为在编译时可以知道局部变量、参数和返回地址所需空间的固定大小,并可以将它们分配于BSS段。
在绝大多数处理器中,堆栈是向下增长的,也就是朝着低地址方向生长。
 
8、过程活动记录:(P128)

在X86架构中,运行时系统维护一个指针(常位于寄存器中),通常称为fp,用于提示活动堆栈结构。它的值是最靠近堆栈顶部的过程活动记录的地址。
 
9、不能从函数中返回一个指向该函数局部自动变量的指针。因为当进入该函数时,自动变量在堆栈中分配。当函数结束后,变量不复存在,它所占用的堆栈空间被收回,可能在任何时候被覆盖。如果想返回一个指向在函数内部定义的变量的指针时,要把那个变量声明为static。(P132)
 
10、尽管通常说“将过程活动记录压倒堆栈中”,但过程活动记录并不一定要存在于堆栈中。事实上,尽可能地把过程活动记录的内容放到寄存器中会使函数调用的速度更快,效果更好。(P132)
 
11、对于如何在进程中支持不同的控制线程是比较清楚的了,只要简单地为每个控制线程分配不同的堆栈即可。(P133)
 
12、setjmp()和longjmp()是通过操纵过程活动记录实现的,这两个函数协同工作:(P133)
(1)、setjmp(jmp_buf j)必须首先被调用。它表示“使用变量j记录现在的位置。函数返回零。”
(2)、longjmp(jmp_buf j, int i)可以接着被调用。它表示“回到j所记录的位置,让它看上去像是从原先的setjmp()函数返回一样。但是函数返回i,使代码能够知道它实际上是通过longjmp()返回的。”
(3)、当使用于longjmp()时,j的内容被销毁。
setjmp保存了一份程序的计数器和当前的栈顶指针。longjmp恢复这些值,有效地转移控制并把状态重置回保存状态的时候。
 
13、longjmp会导致转移,但是它和goto又有不同,区别如下:(P133)
(1)、goto语句不能跳出C语言当前的函数;
(2)、用longjmp只能跳回到曾经到过的地方。在执行setjmp的地方仍留有一个过程活动记录。longjmp接收一个额外的整型参数并返回它的值,这可以知道是由longjmp转移到这里的还是从上一条语句执行后自然而然来到这里的。
需要注意的是:保证局部变量在longjmp过程中一直保持它的值得唯一可靠方法是把它声明为volatile。
setjmp/lognjmp最大的用途是错误恢复。只要还没有从函数中返回,一旦发现一个不可恢复的错误,可以把控制转移到主输入循环,并从那里重新开始。setjmp和lognjmp在C++中变异为异常处理机制“catch”和“throw”。
 
14、标准的代码优化技巧包括:消除循环、函数代码就地扩展、公共子表达式消除、改进寄存器分配、省略运行时对数组边界的检查、循环不变量代码移动、操作符长度削减(把指数操作变为乘法操作,把乘法操作变为移位操作或加法操作等)等。
 
二、问题
1、查看frame.h文件?(P131)
 
2、要求读入一个内容是10000个数值的文件,并计算这些数值的平均数。你的程序的运行时间必须尽可能地短。(P140)
posted on 2012-04-30 23:18  谷堆旁边  阅读(364)  评论(0编辑  收藏  举报