Анализ двоичного вывода g ++

Учитывая следующую программу:

unsigned char g1[] = { 0x1a, 0x2a, 0x3a, 0x4a };
static unsigned char g2[] = { 0x1b, 0x2b, 0x3b, 0x4b };

int main()
{
unsigned char l1[] = { 0x1c, 0x2c, 0x3c, 0x4c };
static unsigned char l2[] = { 0x1d, 0x2d, 0x3d, 0x4d };
}

После того, как я скомпилировал его просто с помощью «g ++ test.cpp -o test» и запустил hexdump -C в двоичном файле, я понял, что последовательности для g1, g2 и l2 можно легко найти в двоичном файле. Только последовательность для l1 (1c 2c 3c 4c), по-видимому, отсутствует в любом месте двоичного файла.

Кто-нибудь знает, почему это так?

2

Решение

Потому что он расположен в стеке вызова этой функции. Обычно в подобных случаях одна из двух вещей будет счастливой:

  1. Компилятор будут сохраните эту последовательность в разделе данных, а затем, по существу, запишите ее в буфер стека.

  2. Компилятор, по существу, жестко кодирует команды «перемещения» для повторной сборки последовательности из наибольшего непосредственного значения набора команд (часто это 4-байтовое целое).

Если это не было оптимизировано, как упомянуто «раскрутка», то, вероятно, происходит # 2. Глядя на разборку, пропрограмма (или предварительно собранный ASM-код) покажет вам лучше. использование -S и посмотрите на файлы .s.

4

Другие решения

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

3

l1[] а также l2[] удаляются во время оптимизации компилятора, потому что оба local and unused variables (нет никаких шансов, что обе переменные будут использоваться где-либо еще).

Вы можете скомпилировать свой код с -S возможность генерировать ассемблерный код: и нет определения для l1[] а также l2[] в основном даже нигде:

входной файл был x.cскомпилировано с командой gcc -S x.c создать файл сборки x.s

main:
pushl   %ebp
movl    %esp, %ebp
subl    $16, %esp
movb    $28, -4(%ebp)
movb    $44, -3(%ebp)
movb    $60, -2(%ebp)
movb    $76, -1(%ebp)
leave
ret
.size   main, .-main
.data
.type   l2.1250, @object
.size   l2.1250, 4

Но вы можете найти определение для g1[] and g2[],

    .file   "x.c".globl g1
.data
.type   g1, @object
.size   g1, 4
g1:
.byte   26
.byte   42
.byte   58
.byte   74
.type   g2, @object
.size   g2, 4
g2:
.byte   27
.byte   43
.byte   59
.byte   75
.text
.globl main
.type   main, @function

Дополнительно , Было бы интересно узнать, если вы компилируете, если вы компилируете свой код с флагом -O3 флаг оптимизации уровня 3 тогда только определение g1[] настоящее. и глобальные статические переменные (приватные для файла) также удаляются.

входной файл был x.cскомпилировано с командой gcc -S -O3 x.c создать файл сборки x.s

ниже:

    .file   "x.c".text
.p2align 4,,15
.globl main
.type   main, @function
main:
pushl   %ebp
movl    %esp, %ebp
popl    %ebp
ret
.size   main, .-main
.globl g1
.data
.type   g1, @object
.size   g1, 4
g1:
.byte   26
.byte   42
.byte   58
.byte   74
.ident  "GCC: (Ubuntu/Linaro 4.4.4-14ubuntu5) 4.4.5".section    .note.GNU-stack,"",@progbits

g1[] только глобальные данные присутствуют, и g2[] удаляется в -O3,

g2[] использовать определенный static unsigned char g2[] так что доступ только внутри этого файла и не использовать, так что снова не используется. Но g1[] является глобальным, это может быть полезно другой программой, если другой файл включает это. И компилятор не допускает оптимизации глобальных объектов.

Ссылка: Как я могу предотвратить компиляцию моих «неиспользуемых» глобальных переменных?

Итак, все это благодаря оптимизации компилятора!

0
По вопросам рекламы [email protected]