Распределение переменных в сегментах - PullRequest
1 голос
/ 11 декабря 2010

В качестве проверки я попробовал следующий код:

const int i = 100;
static int m = 90;
const int p = 40;
int x;

main()
{
    const int j = 40;
    static int k = 40;
    const int n;

    char *p = "Rama";
}

Поэтому, пожалуйста, сообщите, какая переменная идет в какой сегмент, поскольку я получил следующий вывод через компилятор gcc.Когда я написал

size ./a.out

, я получил:

text   data   bss    dec   hex   filename
865    268     12   1145   479   ./a.out

Ответы [ 4 ]

1 голос
/ 11 декабря 2010

Вы можете использовать нм . Вот пример: test.c содержит пример, который вы разместили:

gcc -o test test.c
nm -p -m test

00001fb0 (__TEXT,__text) non-external (was a private external) dyld_stub_binding_helper
00001fc4 (__TEXT,__text) non-external (was a private external) __dyld_func_lookup
00002010 (__DATA,__data) non-external dyld__mach_header
00002014 (__DATA,__data) non-external _m
00002018 (__DATA,__data) non-external _k.1510
0000200c (__DATA,__data) external _NXArgc
00002008 (__DATA,__data) external _NXArgv
00002000 (__DATA,__data) external ___progname
00001000 (absolute) [referenced dynamically] external __mh_execute_header
00002004 (__DATA,__data) external _environ
00001ff0 (__TEXT,__literal4) external _i
00001fd2 (__TEXT,__text) external _main
00001ff4 (__TEXT,__literal4) external _p
00002038 (__DATA,__common) external _x
00001f70 (__TEXT,__text) external start
         (undefined [lazy bound]) external _exit (from libSystem)

Вы можете использовать метод, описанный здесь , чтобы контролировать, к какому сегменту идут переменные. (В MS VC вы можете использовать #pragme data_seg("segname")).

1 голос
/ 11 декабря 2010

Обычно неинициализированные данные попадают в BSS, а инициализированные данные - в DATA (см. здесь ).

Но ISO C не требует такого рода вещей, это полностью проблема реализации,dec и hex в вашем вопросе являются суммами трех других в десятичном и шестнадцатеричном формате соответственно:

865 + 268 + 12 = 1145 = 0x479

Если вы действительно хотите знать, есть различные инструменты, которые вы можете использовать, такие какgcc -S при компиляции для получения вывода на ассемблере, или nm и его собратья для просмотра внутри объектных файлов.

1 голос
/ 11 декабря 2010

Переменные и прочее идут туда, куда их хочет поместить ваш компилятор.У вас может быть какой-то выбор в отношении поведения компилятора с помощью опций.

Возможно, вы захотите посетить следующие ссылки:

http://en.wikipedia.org/wiki/A.out

http://en.wikipedia.org/wiki/Executable_and_Linkable_Format

0 голосов
/ 11 декабря 2010

Я думаю, вы путаетесь между значениями static и const, что понятно, поскольку вы (и я!) Часто забываете их значение, как только однажды прочитали теорию.

1) Во-первых, const.Что означает const, так это то, что мы не будем изменять значение переменной через эту «ссылку» на нее.Это действительно полезно для аргументов функций, особенно при использовании указателей, так что вы не редактируете значения, которые вы не собирались.Например, произвольно:

void add(int* result, const int* a, const int* b)

Это объявление означает, что если мы случайно набрали a = result + b;, компилятор должен пожаловаться и отказаться от компиляции.В этом случае мы назвали переменные таким образом, что мы не должны перезаписывать их даже случайно, но в более сложных сценариях это может произойти.

Однако, как говорит pmg, это не означает, чтозначение не изменится;это просто означает, что когда мы говорим об этой версии этого адреса / значения, мы не будем ее менять.Я хочу сказать, что полезно защищать аргументы, которые вы не собираетесь изменять, на случай, если вы случайно попытаетесь их изменить.Если вы хотите, чтобы по-настоящему фиксированное значение часто использовалось препроцессором, например, #define TRUE 1.

2) Теперь static.Статический означает «не виден за пределами этого блока компиляции».Это похоже на понятие приватности в классах, и я подчеркиваю, но не эквивалентно ему, но в данном случае мы говорим обо всем файле Си.Итак, если мы находимся в файле helloworld.c и вверху вы пишете:

static int x = 10;

Вы не сможете использовать эту версию x в helloworld2.c.

3).мы в этом, мы могли бы также сделать другое слово inline.inline, на мой взгляд, является своего рода более приятным способом создания макросов и означает «компилятор, вы должны действительно поместить полученный код этого кода туда, куда вы его вызываете, вместо того, чтобы обходиться нам вызовом функции».Оптимизация компиляторов может сделать это в любом случае, но это действует как явная инструкция для вставки, где это возможно.

Таким образом, эти функции включают все элементы управления языка, а не место, где переменная помещается в различные сегменты исполняемого файла.Как говорит pmg , компилятор может делать все, что ему захочется.

Если вы хотите понять, что сделал компилятор, используйте gcc -S.Это дает вам вывод на языке ассемблера gcc, который будет в формате AT & T.Попробуйте это с различными флагами gcc -Ox, где x=0,1,2,3, чтобы получить представление о том, как работает оптимизация.

Наконец, стоит отметить, что на самом деле a.out - это просто имя;ваше современное ядро, вероятно, скомпилировано без поддержки a.out бинарных файлов.

Я думаю, что этот вопрос вы действительно пытались задать.

...