读书笔记:游戏引擎架构第二版
目的:了解存储空间如何分配,多种C/C++变量类型如何运作,需要认识的C/C++的内存布局。
一 可执行映像
当生成C/C++ 程序时,链接器创建可执行文件,这种流行的可执行文件格式 称为可执行与可链接格式。一些平台的可执行文件格式.elf 作为扩展名,windows上的可执行文件格式使用.exe作为扩展名。
无论是哪种文件格式,可执行文件总是包含程序的部分映像,程序执行时这部分映像会放在内存中。之所以被称为部分映像是因为:由于程序除了把可执行映像置于内存中,一般也会分配额外的内存。
可执行映像被分为几个相连的块,这些块被称为段或者节(section)。每个操作系统的可执行文件布局方式都有些差异,同一个操作系统的不同可执行文件也会有些微差别。一般来说,映像文件最少有以下四个段组成:
·代码段:包含程序中定义的全部函数的可执行机器码;
·数据段:包含全部 获初始化的全局以及静态变量。链接器会为这些变量分配所需的内存,其内存布局将会和程序执行时完全一样,并且链接器会填入适当的初始值。
·BSS段:包含程序中定义的所有未初始化的全局变量和静态变量。(C/C++中明确定义,任何为初始化的全局变量和静态变量皆为零。)不过,与其在BSS段存储可能很大块的零值,链接器只需要简单的存储所需零值的字节个数,足以安置此段内未初始化的全局以及静态变量。当操作系统载入程序时,就会保留BSS段所需的字节个数,并为该部分内存填入0,之后调用程序进入点(比如main())。
·只读数据段:rodata段。包含程序中定义的只读(常量)全局变量。比如所有浮点常量以及所有的const 关键字声明的全局对象实例就属于只读数据段。注意:通常编译器把整数常量,看作是明示常量,并且直接把明示常量插进机器码中,明示常量直接占用代码段的存储空间,不存储于只读数据段。
全局变量,是指由所有函数以及类声明外的文件作用域定义的变量。按照是否被初始化决定存储于数据段还是BSS段。
static关键字可以把全局变量或者函数指明为内部链接,使其不显露在其他的翻译单元。但是除此之外,可以用static关键字来声明置于函数内的全局变量。函数静态变量的词法作用域只在他定义的函数之内(即变量的名字只能在函数内见到)。变量会在第一次调用其函数时被初始化(而不像文件域静态变量,在main()调用前已经被初始化了)。但是,以可执行映像内存布局来说,函数静态变量和文件域静态变量并没有什么区别,都是根据是**否被初始化而分别存储于数据段或者BSS段的**。
二