Copyleft in this article belongs to the gfree.wind@gmail.com, the use of GPL release, can be freely copied, reproduced. However, please maintain the integrity of the document and indicate the original author and original link. It is strictly prohibited to use the document for any commercial purposes.
By gfree.wind@gmail.com
Blog: linuxfocus.blog.chinaunix.net
Recently, I am reviewing the book "Programmer self-cultivation", because the level has improved compared with the previous one, so the reading gains are different.
The following is a more detailed discussion of the content in section BSS of section 3.3.3 in this book. The content of this section is not repeated in this article, but only the conclusion is given. For a global variable, if a value not 0 is initialized, the global variable is saved in the data segment. If the initial value is 0, it is saved in the bss segment, if Initialization is not performed, save it in the common segment and wait for the link to put it into the BSS segment. The third point varies with compiler behaviors. Some compilers directly place uninitialized global variables in the BSS segment.
I will not repeat the above conclusion. I will discuss more details below. From the above content, although uninitialized global variables may be stored in the common section during the compilation phase, they will still be placed in the BSS segment. Can we equate uninitialized global variables with those initially 0?
See the following code:
File test1.c:
# Include <stdio. h>
Int init = 0;
Void init1 ()
{
If (0 = init ){
Init = 1;
Printf ("init1 \ n ");
}
}
Compile gcc-g-c test1.c
File test2.c:
# Include <stdio. h>
Int init = 1;
Void init2 ()
{
If (init ){
Init = 0;
Printf ("init2 \ n ");
}
}
Compile gcc-g-c test2.c
File main. c
Void init1 ();
Void init2 ();
Int main ()
{
Init1 ();
Init2 ();
Return 0;
}
Compile gcc-g-o test main. c test1.o test2.o
An error is reported.
Test2.o :(. data + 0x0): multiple definition of 'init'
Test1.o:/root/work/test/test1.c: 4: first defined here
Collect2: ld returned 1 exit status
Can everyone accept this error? OK, now we make a small change to change int init = 0 in the file test1.c to int init. For test1.c, this change does not affect its logic, because if init is not initialized, the value is also 0.
Current test1.c
# Include <stdio. h>
Int init;
Void init1 ()
{
If (0 = init ){
Init = 1;
Printf ("init1 \ n ");
}
}
Compile gcc-g-c test1.c
Gcc-g-Wall-o test main. c test1.o test2.o
Even if warning is enabled with-Wall, there are no warnings or errors. The output file test has been generated.
Run test
[Root @ Lnx99 test] #./test
Init2
Well, www.2cto.com will discuss why. First, when init in test1.c is initialized to 0, it is a strong symbol even though init is placed in the bss segment. In test2.c, init is defined as 1, which is also a strong symbol, causing an error. In the second case, when init in test1.c is not initialized, although its value is still 0, it is saved in the common section as a weak symbol. When test2.c defines init as a strong symbol, gcc will overwrite the weak symbol with this strong symbol during the link process and will not cause a link conflict error. However, in the running stage, when init1 is entered, the init value is not the expected value, so init1 is not printed.
I think we should be clear about the difference between the BSS and COMMON segments. From this difference, we need to note that when defining global variables, there are two points to note: 1. If this file is only used, add static; 2, even if you cannot use static, you must define an initial value for the global variable, even if the value is 0. This ensures that the variable is a strong symbol. When a name conflict occurs, it can be found instead of being overwritten by unknown values. 3. It is best to avoid global variables or define a unique name.
In the compilation phase, you can use the-fno-common option to disable uninitialized global variables from being placed in the common section.
For the same file, see the following compilation link process:
[Root @ Lnx99 test] # gcc-g-fno-common-c test1.c
[Root @ Lnx99 test] # gcc-g-fno-common-c test2.c
[Root @ Lnx99 test] # gcc-g-fno-common-o test main. c test1.o test2.o
Test2.o :(. data + 0x0): multiple definition of 'init'
Test1.o:/root/work/test/test1.c: 6: first defined here
Collect2: ld returned 1 exit status