2010-12-04 177 views
3

是否有全局变量增加可执行文件的大小?如果是的话如何?它是否仅增加数据段大小或文本段大小?全局变量如何影响可执行文件的大小?

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

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

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

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

回答

5

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

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

2

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

为什么它关系到可执行文件的哪个“部分”增加了?这不是一个修辞问题!

+1

字符串**可**被删除**如果**它实际上并未在任何地方使用。 – 2010-12-04 08:44:15

+0

字符串文字只是一个例子。可能有很多这样的全局变量,它们可能是结构数组,可能会使用字符串,整数等进行初始化。使用malloc为这些全局变量分配内存会减小任何大小吗? – Jay 2010-12-04 08:52:31

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 

其中STR42是在内存中的串"Hello"的位置的符号名。然后当所有东西都链接在一起时,@STR42被内存中字符串的实际虚拟地址替换。

3

答案是实现相关的,但对于稳健的实现,这是它的工作原理与静态存储时间(全球或其他方式)的变量:

  • 每当变量初始化,整个初始化值对象将被存储在可执行文件中。即使只有初始部分被明确初始化(其余部分隐含为零),情况也是如此。
  • 如果该变量是常量并且已初始化,它将位于“文本”段或等效项中。有些系统(基于现代ELF,也许Windows也是?)有一个独立的“rodata”段用于只读数据,以便将其标记为不可执行,与程序代码分开。
  • 非常量初始化变量将位于可执行文件的“数据”段中,该文件在加载程序时由操作系统在写时复制模式下映射到内存中。
  • 未初始化的变量(根据标准隐式为零)在可执行文件本身中没有保留存储空间,而是在操作系统在程序加载时创建的“bss”段中的大小和偏移量。
  • 这样的未初始化变量可能被创建在一个单独的只读“bss”类段中,如果它们是const限定的。
相关问题