理解C中数据bss段的大小命令 [英] understanding size command for data bss segment in C

查看:420
本文介绍了理解C中数据bss段的大小命令的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我收到来自 size 命令的意外输出。

Afaik初始化存储在 data 段中的全局变量和静态变量,并且未初始化并初始化为0个全局/静态变量 bss 段。
$ b

printf(%d,sizeof(int)); 给出 int size 4.但是, bss data 段不会相应增加到4。 p>

  #include  
int main()
{
return 0;
}

C:\程序文件(x86)\Dev-Cpp\MinGW64\bin>大小memory-layout.exe
文本数据bss十六进制文件名
10044 2292 2512 14848 3a00 memory-layout.exe

#include< stdio.h>
int g; //未初始化的全局变量,所以存储在bss段中
int main()
{
return 0;
}

C:\程序文件(x86)\Dev-Cpp\MinGW64\bin>大小memory-layout.exe
文本数据bss十六进制文件名
10044 2292 2528 14864 3a10 memory-layout.exe

原因 bss 增加了16(2528 - 2512)而不是4? (在上面的代码中)

  #include< stdio.h> 
int g = 0; //初始化为0,存储在bss段中
int main()
{
return 0;
}

C:\程序文件(x86)\Dev-Cpp\MinGW64\bin>大小memory-layout.exe
文本数据bss十六进制文件名
10044 2292 2512 14848 3a00 memory-layout.exe

在<$尽管使用全局变量,c $ c> bss 。为什么会这样?

  #include  
int main()
{static int g; //应该位于bss段
返回0;
}

C:\程序文件(x86)\Dev-Cpp\MinGW64\bin>大小memory-layout.ex
文本数据bss十六进制文件名
10044 2292 2512 14848 3a00 memory-layout.exe

c> bss 段尽管使用了静态变量,为什么?



我还有一个问题, dec 代表这里?

解决方案

首先要考虑的是内存对齐。变量和部分可以填充以使它们位于地址边界上。在第二个例子中,你会看到第一个16的增加,这表明填充16字节的边界(2512/16 = 157,2528/16 = 158)。这完全取决于实现。



就C而言,第二个例子与第三个例子不同,因为编译器无法知道 int g 是一个定义或者只是一个在另一个文件中定义的整数的声明(它可以是任何值)。它留下了一个链接器处理的引用,这可能会导致填充差异。



在第三个示例中, g 被显式定义并设置为0,所以编译器知道把它放在BSS部分。



可以用我生成的程序集系统:



int g (本例中没有定义BSS部分)

  .comm g,4,4 





加上

这是链接器处理符号的指令,因为编译器不能完全确定如何处理它。 int g = 0

  .bss 
.align 4
.type g,@object
.size g,4
g:
.zero 4

在这里,编译器确切地知道该做什么,因此为该符号定义了BSS部分。



在我的例子中,链接器以相同的方式解决这些问题。两者都放置在同一地址的BSS部分,因此BSS大小没有差异。您可以使用类似于 nm 的实用程序来检查布局。

  nm  - n file2 file3 | grep g $ 

000000000060103c B g
000000000060103c B g

即在这个系统上 g 在同一个地址。或者,使用调试器:

 (gdb)信息符号0x60103c 
g在/ tmp / file2的.bss节点

还要注意,在最后一个例子中,变量可以进行优化,因为它具有内部链接。 p>

至于 dec ,它只是十进制分段的总和。


I'm getting unexpected output from size command.

Afaik initialized global and static variables stored in data segment and uninitialized and initialized to 0 global/static variables stored in bss segment.

printf("%d",sizeof(int)); gives int size 4. However, bss and data segment is not increasing accordingly to 4.

#include <stdio.h>
int main()
{
    return 0;
}

C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
   text    data     bss     dec     hex filename
  10044    2292    2512   14848    3a00 memory-layout.exe

#include <stdio.h>
int g; //uninitialised global variable so, stored in bss segment
int main()
{
    return 0;
}

C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
   text    data     bss     dec     hex filename
  10044    2292    2528   14864    3a10 memory-layout.exe

why bss increased by 16 (2528 - 2512) instead of 4? (in above code)

#include <stdio.h>
int g=0; //initialised to 0 so, stored in bss segment
int main()
{
    return 0;
}

C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.exe
   text    data     bss     dec     hex filename
  10044    2292    2512   14848    3a00 memory-layout.exe

there is no increment in bss in spite of using global variable. why's that?

 #include <stdio.h>
int main()
{   static int g; //should be on bss segment
    return 0;
}

C:\Program Files (x86)\Dev-Cpp\MinGW64\bin>size memory-layout.ex
   text    data     bss     dec     hex filename
  10044    2292    2512   14848    3a00 memory-layout.exe

no increment in bss segment in spite of using static variable, why?

and I have one more question, what dec represents here?

解决方案

The first thing to consider is memory alignment. Variables and sections can be padded to make them sit on address boundaries. In the second example you are seeing an increase of 16 from the first, which suggests padding for 16-byte boundaries (2512 / 16 = 157, 2528 / 16 = 158). This is entirely implementation dependent.

As far as C is concerned, the second example differs from the third because the compiler cannot know if int g is a definition or just a declaration for an integer defined in another file (where it could be any value). It leaves a reference for the linker to deal with instead, which may lead to differences in padding.

In the third example, g is explicitly defined and set to 0, so the compiler knows to put this in the BSS section.

It's possible to demonstrate this with the generated assembly from my system:

with int g (no BSS section is defined in this case)

.comm   g,4,4

This is a instruction for the linker to deal with the symbol, as the compiler cannot fully determine what to do with it.

with int g = 0

    .bss
    .align 4
    .type   g, @object
    .size   g, 4
g:
    .zero   4

Here the compiler knows exactly what to do and so defines a BSS section for the symbol.

In my case, the linker resolves these identically. Both are placed in the BSS section at the same address, and so there is no difference in BSS size. You can examine the layout with a utility like nm.

nm -n file2 file3 | grep g$

000000000060103c B g
000000000060103c B g

i.e. on this system g is at the same address. Alternatively, with a debugger:

(gdb) info symbol 0x60103c
g in section .bss of /tmp/file2

Note also that in the final example the variable can be optimised out, since it has internal linkage.

As for dec, it is simply the sum of the sections in decimal.

这篇关于理解C中数据bss段的大小命令的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆