6.2.8存储器分配
1. C编译器生成的段
C编译器生成的段有两种基本的类型,即初始化段和未初始化段。
初始化段有:
.cinit段,包含初始化数据表格和常数。
.pinit段,包含实时运行时调用的数据表格。
.const段,包含用const定义(不能同时被volatile定义)的字符串常量和数据。
.switch段,包含switch语句所用表。
.text段,包含所有可执行代码。
未初始化段保留了存储器空间。一段程序可以在运行期间使用这个空间来生成和存储变量。未初始化段有:
.bss段,为全局和静态变量保留了空间。在启动和装载的时候,C启动程序或装载程序从.cinit段(通常在ROM中)复制数据并用这些数据来初始化.bss段中的变量。
.stack段,为C系统堆栈分配存储地址。这个存储地址用来传递变量和局部存储。
.sysstack段,为第二系统堆栈分配存储地址。
.sysmem段,为动态存储分配保留空间。这个空间被malloc、calloc和realloc函数调用。如果C程序不使用这些函数,编译器就不会创建.sysmem段。
.cio段,支持C I/O。这个空间用来作为标签为_CIOBUF_缓冲区。当任何类型的C I/O被执行(如printf和scanf),就会建立缓冲区。缓冲区包含一个对stream I/O类型的内部C I/O命令(和需要的参数)及从C I/O命令返回的数据。.cio段必须放在链接器命令文件中才能使用C I/O。
注意:汇编器生成了叫做.data的段,但C编译器并不使用这个段。
链接器从不同的模块中将段取出并合并,合并后有相同的名字。生成的输出段和适当的存储位置如表6-2所示。
表6-2 段及其存储位置
段 |
存储器类型 |
段 |
存储器类型 |
.text |
ROM或RAM |
.bss |
RAM |
.cinit |
ROM或RAM |
.stack |
RAM |
.const |
ROM或RAM |
.sysstack |
RAM |
.data |
ROM或RAM |
.sysmem |
RAM |
.pinit |
ROM or RAM |
.cio |
RAM |
2. 堆栈
在C编译器中,使用堆栈来放置局部变量、传递参数给函数、保存处理器状态。堆栈被放在存储器的一个连续块中,并从高地址到低地址存放数据。编译器用硬件堆栈指针(SP)来管理堆栈。代码不会检查是否在运行时间内堆栈出现溢出。堆栈溢出出现在堆栈生长超过了分配的存储空间的极限。必须为堆栈分配合适的存储空间。
C55x也支持第二系统堆栈。为了和C54x兼容,系统堆栈保存低16位地址。第二系统堆栈保持C55x的高8位返回地址。编译器使用第二堆栈指针SSP来管理第二系统堆栈。
这两个堆栈的大小都由链接器设置。链接器也会生成全局符号_STACK_SIZE和_SYS STACK_SIZE,并给它们指定一个等于各自堆栈大小的值。两种默认堆栈大小都是1000字节。在链接时间内,通过链接器命令中的-stack或-sysstack选项可以改变堆栈大小。在选择了这个选项后堆栈大小立即被指定为常数。
3.动态存储器分配
由编译器提供的运行时间支持库包含几个在运行时间内为变量动态分配存储器的函数(malloc、calloc和realloc)。
存储器被从一个在.sysmen段定义的全局池(pool)或堆(heap)中分配出来。可以通过-heap size选项和链接器命令来设置.sysmem段的大小。链接器会生成一个全局符号_SYS MEM _SIZE,并为它指定等于heap字节数的值。默认大小为2000字节。
动态分配的对象必须用指针寻址。为了在.bss段中保留空间,可以通过从堆中定义大数组来实现,而不是将其定义为全局或静态变量。
例如,不用如下定义:
struct big table[100];
而使用指针并调用malloc函数:
struct big *table;
table=(struct big*)malloc(100*sizeof(struct big));