全局变量和 .data 部分 [英] Global variables and the .data section

查看:52
本文介绍了全局变量和 .data 部分的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

根据定义存储在 .data 部分的变量是否是具有程序作用域的全局变量?换句话说,这两个词是同义词,一个暗示另一个,或者,例如,可能有一个 global 变量没有存储在 .data 部分,或者不是全局的标签/变量?

Is a variable that is stored in the .data section by definition a global variable that has program scope? In other words are these two words synonymous and one implies the other, or, for example would it be possible to have a global variable that is not stored in the .data section, or a label/variable that is not global?

举个简单的例子:

// this is compiled as in the .data section with a .globl directive
char global_int = 11;

int main(int argc, char * argv[])
{

}

会编译成类似的东西:

global_int:
        .byte   11
main:
    ...

但我正在查看这两个术语——全局和在 .data 部分"是否存在.是一样的还是有反例的.

But I'm seeing if the two terms -- global and "in the .data section" are the same thing or if there are counterexamples.

推荐答案

有两个不同的概念:哪个节"是一个变量进入它的可见性"

There are two different concepts: Which "section" a variable goes into and its "visibility"

为了比较,我添加了一个 .bss 部分变量:

For comparison, I've add a .bss section variable:

char global_int = 11;
char nondata_int;

int
main(int argc, char *argv[])
{
}

使用 cc -S 编译产生:

    .file   "fix1.c"
    .text
    .globl  global_int
    .data
    .type   global_int, @object
    .size   global_int, 1
global_int:
    .byte   11
    .comm   nondata_int,1,1
    .text
    .globl  main
    .type   main, @function
main:
.LFB0:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    .cfi_offset 6, -16
    movq    %rsp, %rbp
    .cfi_def_cfa_register 6
    movl    %edi, -4(%rbp)
    movq    %rsi, -16(%rbp)
    movl    $0, %eax
    popq    %rbp
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE0:
    .size   main, .-main
    .ident  "GCC: (GNU) 8.3.1 20190223 (Red Hat 8.3.1-2)"
    .section    .note.GNU-stack,"",@progbits

注意 .dataglobal_int 变量放在数据部分.并且,.commnondata_int 放入 .bss 部分

Note the .data to put the global_int variable in the data section. And, .comm to put nondata_int into the .bss section

另外,注意 .globl 以使变量具有全局可见性(即可以被其他 .o 文件看到).

Also, note the .globl to make the variables have global visibility (i.e. can be seen by other .o files).

松散地,.data 和/或 .bss 是变量放入的 sections.并且,全局 [.globl] 是可见性.如果你这样做了:

Loosely, .data and/or .bss are the sections that the variables are put into. And, global [.globl] are the visibility. If you did:

static int foobar = 63;

然后,foobar 会进入 .data 部分,但是是本地的.在下面的 nm 输出中,不是 D,而是 d 来表示本地/静态可见性.其他 .o 文件将无法看到这个[或链接到它].

Then, foobar would go into the .data section but be local. In the nm output below, instead of D, it would be d to indicate local/static visibility. Other .o files would not be able to see this [or link to it].

.o 程序的 nm 产生:

0000000000000000 D global_int
0000000000000000 T main
0000000000000001 C nondata_int


并且,最终可执行文件的 nm -g 产生:

000000000040401d B __bss_start
0000000000404018 D __data_start
0000000000404018 W data_start
0000000000401050 T _dl_relocate_static_pie
0000000000402008 R __dso_handle
000000000040401d D _edata
0000000000404020 B _end
0000000000401198 T _fini
000000000040401c D global_int
                 w __gmon_start__
0000000000401000 T _init
0000000000402000 R _IO_stdin_used
0000000000401190 T __libc_csu_fini
0000000000401120 T __libc_csu_init
                 U __libc_start_main@@GLIBC_2.2.5
0000000000401106 T main
000000000040401e B nondata_int
0000000000401020 T _start
0000000000404020 D __TMC_END__


更新:

感谢您的回答.关于 And,.commnondata_int 放入 .bss 部分.你能解释一下吗?我没有看到任何对 .bss 的引用,那么这两个是如何相关的?

thanks for this answer. Regarding And, .comm to put nondata_int into the .bss section. Could you please explain that a bit? I don't see any reference to .bss so how are those two related?

当然.可能有一个更严格的解释,但松散,当你这样做时:

Sure. There's probably a more rigorous explanation, but loosely, when you do:

int nondata_int;

您正在定义一个公共"段变量[历史渊源来自Fortran的common].

You are defining a "common" section variable [the historical origin is from Fortran's common].

当链接[创建最终的可执行文件]时,如果no其他.o[或.a]已经为它声明了一个值,它将作为 B 符号放入 .bss 部分.

When linking [to create the final executable], if no other .o [or .a] has declared a value for it, it will be put into the .bss section as a B symbol.

但是,如果另一个 .o 已经定义了它(例如define_it.c):

But, if another .o has defined it (e.g. define_it.c):

int nondata_int = 43;

在那里,define_it.o 会将它作为 D 符号放入 .data 部分

There, define_it.o will put it in the .data section as a D symbol

然后,当您将两者联系起来时:

Then, when you link the two:

gcc -o executable fix1.o define_it.o

然后,在executable中,它会作为D符号进入.data部分.

Then, in executable, it will go to the .data section as a D symbol.

因此,.o 文件具有/使用 .comm [汇编指令] 和 C 公共部分.

So, .o files have/use .comm [the assembler directive] and C common section.

可执行文件只有 .data.bss.因此,给定 .o 文件,如果它从未被初始化并且 .data 如果 any .o 已经初始化它.

Executables have only .data, and .bss. So, given the .o files a common symbol goes to [is promoted to] .bss if it has never been initialized and .data if any .o has initialized it.

松散地,.comm/C 是一个建议,.data.bss 是一个承诺"

Loosely, .comm/C is a suggestion and .data and .bss is a "commitment"

这是一种很好的方式.从技术上讲,在 fix1.c 中,如果我们事先知道我们将与 define_it.o 链接,我们会[可能]想要要做:

This is a nicety of sorts. Technically, in fix1.c, if we knew beforehand that we were going to be linked with define_it.o, we would [probably] want to do:

extern char nondata_int;

然后,在 fix1.o 中,将被标记为未定义"符号(即 nm 将显示 U).

Then, in fix1.o, the would be marked as an "undefined" symbol (i.e. nm would show U).

但是,如果fix1.o没有链接到任何定义符号的东西,链接器就会抱怨一个未定义的符号.

But, then, if fix1.o were not linked to anything that defined the symbol, the linker would complain about an undefined symbol.

公共符号允许我们拥有多个 .o 文件,每个:

The common symbol allows us to have multiple .o files that each do:

int nondata_int;

它们都产生 C 符号.链接器将所有内容组合起来以生成单个符号.

They all produce C symbols. The linker combines all to produce a single symbol.

所以,常见的 C 符号是:

So, again common C symbols are:

我想要一个名为 X 的全局变量,并且我希望它与任何其他 .o 文件中的 X 相同,但不要抱怨符号被多重定义.如果那些 .o 文件中的 one [和 only one] 给它一个 initialized 值,我想从该价值中受益.

I want a global named X and I want it to be the same X as found in any other .o files, but don't complain about the symbol being multiply defined. If one [and only one] of those .o files gives it an initialized value, I'd like to benefit from that value.

历史上......

IIRC [我可能错了],common 被添加到 [链接器] 以支持 Fortran COMMON 声明/变量.

IIRC [and I could be wrong about this], common was added [to the linker] to support Fortran COMMON declarations/variables.

也就是说,所有的 fortran .o 文件都只是将一个符号声明为 common [其全局概念],但希望 fortran 链接器将它们组合起来.

That is, all fortran .o files just declared a symbol as common [its concept of global], but the fortran linker was expected to combine them.

经典/旧版 fortran 只能将变量指定为 COMMON(即在 C 中,相当于 int val;)但 fortran 却没有有全局初始值设定项(即它没有extern int val;int val = 1;)

Classic/old fortran could only specify a variable as COMMON (i.e. in C, equivalent to int val;) but fortran did not have global initializers (i.e. it did not have extern int val; or int val = 1;)

这对 C 很有用,因此,在某个时候添加了它.

This common was useful for C, so, at some point it was added.

在过去的美好时光 (tm),常见的链接器类型存在,除了一个 .o 文件和一个 [并且只有一个] 声明它.声明它的 .o 可以用一个值来定义它(例如)int val = 1;without(例如)intval; 但所有其他 .o 文件必须使用 extern int val;

In the good old days (tm), the common linker type did not exist and one had to have an explicit extern in all but one .o file and one [and only one] that declared it. That .o that declared it could define it with a value (e.g.) int val = 1; or without (e.g.) int val; but all other .o files had to use extern int val;

这篇关于全局变量和 .data 部分的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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