gcc:编译为BSS的线程局部变量

rpl*_*iko 3 c multithreading gcc nm

我是新手,在我的Ubuntu 14.04计算机上使用i686/32位架构测试线程本地存储(TLS)类gcc(版本4.8.2).

在尝试找出__thread关键字是否具有所需效果时,我使用gcc test.c(无错误或警告)编译此简约测试程序:

#include <stdio.h>

__thread int i;

int main() {
  i = 7;
  printf("%d\n",i);
}
Run Code Online (Sandbox Code Playgroud)

并使用该工具nm检查i目标代码中符号的存储类:

nm a.out | grep ' i'
Run Code Online (Sandbox Code Playgroud)

结果是

00000000 B i
Run Code Online (Sandbox Code Playgroud)

这意味着它i被视为一个共同的全局未初始化变量(存储在BSS部分).根据man nm,线程本地存储变量由字母表示L,而不是B.

这有什么不对?

这是一个nm问题还是一个真正的问题?

Fil*_*ves 5

没问题,只是nm(1)写输出的方式.

nm(1)平台之间的默认输出格式(和信息)是不同的(例如nm(1),我的Linux桌面的联机帮助页甚至没有提到L线程本地存储).

但是,如果启用SysV输出格式-fs,则会得到更详细的输出:

$ nm -fs a.out
Symbols from a.out:

Name                  Value           Class        Type         Size             Line  Section

...

i                   |0000000000000000|   B  |               TLS|0000000000000004|     |.tbss
...
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,使用此输出格式i被标识为列下的本地线程Type,并且它存在于.tbss.

如果您的发行版的联机帮助页提到了L线程本地存储的标志,并且您没有以默认输出格式看到它,我会说这是一个错误nm(1).