C编译器对全局变量的特殊内存分配



当我在main外声明某些变量时,以某种特殊的方式存储它们。

int i=1,j=1;
void main(void)
{
     printf("%dn%d",&i,&j);
}

如果ij均未初始化或等于0或等于某些正值,则它们存储在内存中的连续地址空间中,而如果i=0j = some +ve integer,则其地址会被相当较大的距离分开。

问题是,当它们存储在连续地址空间上时,会导致一些实际的性能问题,例如false共享(请在此处查看)。我了解到,为了防止这种情况,变量的地址之间应该有一些空间,而i=0j=any +ve value

自动提供。

现在,我想了解的是:

  • 为什么仅当一个初始化为0,而另一个初始化为正值时,编译器将变量存储到非连续地址,而
  • 我该如何有意执行编译器自动执行的操作,即将变量分配给相当分开的地址空间。

(使用DEVCPP GCC 4.9.2)

假设您的意思是printf("%p, %pn",(void *)&i,(void *)&j);,请注意以下内容:

  1. C规格不要求在连续内存中分配变量。
  2. 通常以0初始化的Globals保存在BSS部分(这是数据部分的一部分),以节省二进制大小。其他全球群体将保存在数据部分。(取决于实施细节,而不是C规格规定)

我如何有意自动执行编译器?

这是编译器的特定问题,您的编译器文档可能包含答案。

那里一个问题,

  printf("%dn%d",&i,&j);

调用不确定的行为。因此,输出不能以任何方式被证明是合理的。您需要使用 %p格式指定器将相应的参数施加到(void *)以打印指针。

也就是说,C标准既没有施加任何约束,也没有提供有关将变量存储在存储器中的何处和如何存储的指南。由编译器实现决定如何在内存中放置不同的变量。您需要检查使用中的编译器的文档,以找出您的编译器所遵循的规则。

要以通用方式详细说明,一个对象文件由许多段组成,例如

  • 标题(描述性和控制信息)
  • 代码段("文本段",可执行代码)
  • 数据段(初始化的静态变量)
  • 仅阅读数据段(rodata,初始化的静态常数)
  • BSS段(非初始化的静态数据,变量和常数)
  • 链接的外部定义和参考
  • 搬迁信息
  • 动态链接信息
  • 调试信息

,由编译器决定要用于每个段的地址空间(范围/值)。

根据规则,

  • 全局变量(即具有静态存储持续时间)剩余的不定原始化和用0初始化的.bss段。
  • 以非零值初始化的变量放在.data

因此,公平地说,与两个不同段有关的两个变量的地址不会连续。

现在,您的观察结果已签出。

如果ij均未初始化或等于0或等于某些正值,则它们存储在内存中的连续地址空间

是的,然后所有这些都转到.bss.data,然后编译器选择将它们放置一个,通常是一个。

,而如果i=0j = some +ve整数,则它们的地址被相当大的距离分开。

这也是正确的,两个变量现在都放在不同的段中。

相关内容

  • 没有找到相关文章