If I understand correctly, the .bss
section in ELF files is used to allocate space for zero-initialized variables. Our tool chain produces ELF files, hence my question: does the .bss
section actually have to contain all those zeroes? It seems such an awful waste of spaces that when, say, I allocate a global ten megabyte array, it results in ten megabytes of zeroes in the ELF file. What am I seeing wrong here?
相关问题
- Sorting 3 numbers without branching [closed]
- How to compile C++ code in GDB?
- Why does const allow implicit conversion of refere
- thread_local variables initialization
- What uses more memory in c++? An 2 ints or 2 funct
相关文章
- Class layout in C++: Why are members sometimes ord
- How to mock methods return object with deleted cop
- Which is the best way to multiply a large and spar
- C++ default constructor does not initialize pointe
- Selecting only the first few characters in a strin
- What exactly do pointers store? (C++)
- Converting glm::lookat matrix to quaternion and ba
- What is the correct way to declare and use a FILE
A
.bss
section is not stored in an executable file. Of the most common sections (.text
,.data
,.bss
), only.text
(actual code) and.data
(initialized data) are present in an ELF file.The
.bss
section in an ELF file is used for static data which is not initialized programmatically but guaranteed to be set to zero at runtime. Here's a little example that will explain the difference.In this case
bss_test1
is placed into the.bss
since it is uninitialized.bss_test2
however is placed into the.data
segment along with a bunch of zeros. The runtime loader basically allocates the amount of space reserved for the.bss
and zeroes it out before any userland code begins executing.You can see the difference using
objdump
,nm
, or similar utilities:This is usually one of the first surprises that embedded developers run into... never initialize statics to zero explicitly. The runtime loader (usually) takes care of that. As soon as you initialize anything explicitly, you are telling the compiler/linker to include the data in the executable image.
That is correct, .bss is not present physically in the file, rather just the information about its size is present for the dynamic loader to allocate the .bss section for the application program. As thumb rule only LOAD, TLS Segment gets the memory for the application program, rest are used for dynamic loader.
About static executable file, bss sections is also given space in the execuatble
Embedded application where there is no loader this is common.
Suman
Has been some time since i worked with ELF. But i think i still remember this stuff. No, it does not physically contain those zeros. If you look into an ELF file program header, then you will see each header has two numbers: One is the size in the file. And another is the size as the section has when allocated in virtual memory (
readelf -l ./a.out
):Headers of type
LOAD
are the one that are copied into virtual memory when the file is loaded for execution. Other headers contain other information, like the shared libraries that are needed. As you see, theFileSize
andMemSiz
significantly differ for the header that contains thebss
section (the secondLOAD
one):For this example code:
The ELF specification says that the part of a segment that the mem-size is greater than the file-size is just filled out with zeros in virtual memory. The segment to section mapping of the second
LOAD
header is like this:So there are some other sections in there too. For C++ constructor/destructors. The same thing for Java. Then it contains a copy of the
.dynamic
section and other stuff useful for dynamic linking (i believe this is the place that contains the needed shared libraries among other stuff). After that the.data
section that contains initialized globals and local static variables. At the end, the.bss
section appears, which is filled by zeros at load time because file-size does not cover it.By the way, you can see into which output-section a particular symbol is going to be placed by using the
-M
linker option. For gcc, you use-Wl,-M
to put the option through to the linker. The above example shows thata
is allocated within.bss
. It may help you verify that your uninitialized objects really end up in.bss
and not somewhere else:GCC keeps uninitialized globals in a COMMON section by default, for compatibility with old compilers, that allow to have globals defined twice in a program without multiple definition errors. Use
-fno-common
to make GCC use the .bss sections for object files (does not make a difference for the final linked executable, because as you see it's going to get into a .bss output section anyway. This is controlled by the linker script. Display it withld -verbose
). But that shouldn't scare you, it's just an internal detail. See the manpage of gcc.