9

I have the following C code:

   //declared at the beginning of the CAStar.c file:
    int TERRAIN_PASSABLE = 1;
    int TERRAIN_IMPASSABLE = 0;
    int TERRAIN_SOME_WHAT_PASSABLE = 2;

I've noticed that for any of these variables, if they have a non-zero value, they are reported by the "nm" command as type "D" (initialized):

_TERRAIN_PASSABLE          |00000008|   D  |
_TERRAIN_SOME_WHAT_PASSABLE|00000004|   D  |

However, those initialized to 0 are reported as "B" (uninitialized):

_TERRAIN_IMPASSABLE        |00000000|   B  |

Why the difference between "initialized with 0" and "initialized with something else but 0" ?

Shivan Dragon
  • 15,004
  • 9
  • 62
  • 103
  • 2
    It might be an optimization where the compiler does not initialize a heap variable to zero as it expects zeroed-out memory from the OS… just a guess though. – ypnos Dec 10 '13 at 10:14
  • @ypnos Well, to be honest I kindda thought along those lines as well. But then, I left one of those variables really uninitialized (just: "int TERRAIN_SOME_WHAT_PASSABLE;"). This time around the variable was reported as "C", so (yet again) not the same as if initialized with 0 (and also not the same as if initialized with non-0). – Shivan Dragon Dec 10 '13 at 10:17
  • Because ld.so initialises everything to zero. Nothing to do with your app's runtime memory allocation (@ypnos) - just means that the runtime linker doesn't have to set the variables to anything special. – Nicholas Wilson Dec 10 '13 at 10:18
  • 3
    Please clarify where these variables are declared, as it matters a lot. For now, all answers are just guessing that the variables are declared at file scope ("globals"). – Lundin Dec 10 '13 at 10:22
  • @Lundin You are right, I'm gonna update the code snippet. Sorry and thanks. – Shivan Dragon Dec 10 '13 at 10:28
  • This can be viewed as an optimization. Among other things, a process may have objects that are initialized to zero and objects that are not initialized. For the uninitialized objects, the system could just give them whatever memory it has available. But, in multi-user operating systems, this is a security violation: It would let processes see data from other processes. So data must be purged before reuse. This is commonly done by zeroing. The result is that both zero-initialized and uninitialized data are assigned zero-filled memory. Since they are handled the same, they can be put together. – Eric Postpischil Dec 10 '13 at 14:36

2 Answers2

5

This is more or less about how BSS works and how it is used. B means that variable will be placed in BSS section (and you are right it is uninitialized data section). D means that the symbol is placed in initialized data section.

Read for example this article to know bit more about how BSS works and what it is used for.

codewarrior
  • 1,269
  • 1
  • 9
  • 14
  • 1
    I think that calling BSS uninitialized is confusing, because it really is zero-initialized. Many compilers allow placing data to `.no_init` section or similar, which is truly uninitialized. – user694733 Dec 10 '13 at 10:30
  • Thanks, I get it now. It's basically a: "here's all the variables which have default values" list that doesn't contain those actual default values as well, to save space (right?) – Shivan Dragon Dec 10 '13 at 10:31
  • @user694733 I was thinking the same thing, maybe it should be named something more expressive, "uninitialized" is a bit confusing. – Shivan Dragon Dec 10 '13 at 10:32
4

Most likely these variables are declared at file scope, giving them static storage duration.

All variables with static storage duration are, for optimization purposes, sorted in two categories by the compiler/linker: initialized to 0 or initialized to something else. Variables initialized to zero are placed in a memory segment usually referred to as .bss, while those who are initialized to another value are placed in .data.

The reason for this is that .bss variables can be initialized much faster if the are allocated in adjacent memory. Basically they would be initialized with a single memset. Also, it will reduce the amount of ROM needed. Releated question with details.

EDIT

The reason .bss variables end up under uninitialized is likely because there is a rule in the C language (C11 6.7.9/10) stating that all static storage duration variables that aren't initialized explicitly by the programmer (they are "uninitialized"), shall be initialized to zero

Community
  • 1
  • 1
Lundin
  • 195,001
  • 40
  • 254
  • 396