gcc: локальная переменная потока, скомпилированная как BSS
Я новичок и тестирую класс локального хранилища (TLS) с gcc
(версия 4.8.2) на моем компьютере с Ubuntu 14.04 с архитектурой i686/32 bit.
В попытке выяснить, является ли __thread
Ключевое слово имеет желаемый эффект, я собираю эту минималистичную тестовую программу с gcc test.c
(без ошибок или предупреждений):
#include <stdio.h>
__thread int i;
int main() {
i = 7;
printf("%d\n",i);
}
и использовать инструмент nm
проверить класс хранения символа i
в коде объекта:
nm a.out | grep ' i'
Результат
00000000 B i
Который означает, что i
рассматривается как общая глобальная неинициализированная переменная (хранится в разделе BSS). В соответствии с man nm
, переменные локального хранилища потока обозначаются буквой L
не B
,
Что здесь не так?
Это nm
проблема или реальная проблема?
2 ответа
Там нет проблем, это просто способ nm(1)
пишет вывод.
nm(1)
Формат вывода по умолчанию (и информация) отличается на разных платформах (например, на странице man для 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
...
Как вы можете видеть, используя этот формат вывода i
идентифицируется как локальный поток под столбцом Type
и живет в .tbss
,
Если на странице вашего дистрибутива упоминается L
флаг для локального хранилища потока, и вы не видите его в формате вывода по умолчанию, я бы сказал, что это ошибка в nm(1)
,
Ваш код слишком минимален. Количество потоков не будет известно до времени выполнения, поэтому переменная, которую вы видите в исполняемом файле, является переменной, которая main
буду использовать. Дополнительные копии переменной будут выделяться при создании дополнительных потоков.
Вот минимальная программа, которая демонстрирует переменные потока.
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
__thread int i;
void *foo( void *args )
{
i = 8;
printf( "foo: %d\n", i );
return NULL;
}
int main( void )
{
i = 7;
printf( "main:%d\n", i );
pthread_t pid;
if ( pthread_create( &pid, NULL, foo, NULL ) != 0 )
exit( 1 );
pthread_join( pid, NULL );
printf( "main:%d\n", i );
}