3

拥有全局变量会增加可执行文件的大小吗?如果是怎么办?它是只增加数据部分的大小还是增加文本部分的大小?

如果我有一个全局变量和初始化如下:

char g_glbarr[1024] = {"jhgdasdghaKJSDGksgJKASDGHKDGAJKsdghkajdgaDGKAjdghaJKSDGHAjksdghJKDG"};

现在,这是否将 1024 添加到数据部分并将初始化字符串的大小添加到文本部分?

相反,如果为这个数组静态分配空间,如果我 malloc 它,然后做一个 memcpy,只有数据部分的大小会减少,或者文本部分的大小也会减少?

4

4 回答 4

6

是的,它确实。基本上编译器将它们存储到数据段。有时,如果您在代码中使用常量 char 数组(例如printf("<1024 char array goes here");),它将转到数据段(AFAIK 一些旧编译器 /Borland?/ 可能会将其存储在文本段中)。您可以强制编译器将全局变量放在自定义部分中(对于 VC++,它是#pragma data_seg(<segment name>))。

动态内存分配不会影响数据/文本段,因为它在堆中分配内存。

于 2010-12-04T08:49:49.037 回答
3

答案是依赖于实现的,但对于理智的实现,这就是它对具有静态存储持续时间(全局或其他)的变量的工作方式:

  • 每当初始化变量时,对象的整个初始化值都将存储在可执行文件中。即使只有初始部分被显式初始化(​​其余部分隐式为零)也是如此。
  • 如果变量是常量且已初始化,它将位于“文本”段或等效项中。某些系统(基于现代 ELF 的系统,也许还有 Windows?)有一个单独的“rodata”段用于只读数据,以允许将其标记为不可执行,与程序代码分开。
  • 非常量初始化变量将位于可执行文件的“数据”段中,在加载程序时,操作系统以写时复制模式将其映射到内存中。
  • 未初始化的变量(根据标准隐式为零)将不会在可执行文件本身中保留存储空间,而是在“bss”段中保留大小和偏移量,该段由操作系统在程序加载时创建。
  • 如果这些未初始化的变量是 - 限定的,则可以在单独的只读“bss”类段中创建它们const
于 2010-12-04T15:55:34.333 回答
2

我不是以专家的身份说话,但我猜想在你的程序中简单地使用那个史诗般的字符串文字会增加你的可执行文件的大小。你用那个字符串文字做什么并不重要,因为它必须存储在某个地方

为什么增加可执行文件的哪个“部分”很重要?这不是一个反问句!

于 2010-12-04T08:40:45.187 回答
1

答案对实现有点敏感,但总的来说,不会。您g_glbarr实际上是指向 的指针char或地址。字符串本身会被放入带有常量字符串的数据段,并g_glbarr在编译时成为字符串地址的符号。您最终不会为指针分配空间,编译器只是在链接时解析地址。

更新

@Jay,有点像。整数(通常)只是内联的:编译器将尽可能接近将常量放入代码中,因为这是一种常见的情况,大多数普通架构都有一种直接的方式来从直接数据中进行操作。字符串常量仍将位于某些只读数据段中。所以当你做类似的事情时:

// warning: I haven't compiled this and wouldn't normally
// do it quite this way so I'm not positive this is
// completely grammatical C
struct X {int a; char * b; } x = { 1, "Hello" } ; 

成为1“立即”数据,在"Hello"某处分配只读数据,编译器只会生成一些分配一段读写数据的东西,看起来像

x:
x.a:   WORD    1
x.b    WORD    @STR42

whereSTR42是字符串"Hello"在内存中位置的符号名称。然后,当所有内容链接在一起时,将@STR42替换为内存中字符串的实际虚拟地址。

于 2010-12-04T08:52:20.457 回答