2

给定以下程序:

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) 的序列,它显然不存在于二进制文件的任何地方。

有人知道这是为什么吗?

4

3 回答 3

4

因为它是在该函数调用的堆栈上分配的。通常在这种情况下,会发生以下两种情况之一:

  1. 编译器将该序列存储在数据部分中,然后基本上将其 memcpy 到堆栈缓冲区中。

  2. 编译器本质上对“移动”指令进行硬编码,以从指令集的最大立即值(通常是 4-bye int)重新组装序列。

如果它没有被优化,就像提到的“放松”,那么#2 可能正在发生。查看反汇编程序(或预组装的 asm 代码)会更好地向您展示。使用 -S并查看 .s 文件。

于 2013-01-16T13:36:48.450 回答
3

我的猜测是,因为它是非static自动的(非全局的),所以知道没有人能够从外部引用它是微不足道的。由于它没有被使用,它可以被丢弃。

于 2013-01-16T13:34:33.637 回答
0

l1[]并且l2[]在编译器优化期间被删除,因为两者都是local and unused variables(这两个变量都不会在其他任何地方使用)。

您可以使用选项编译代码以生成汇编代码:并且在 main-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[]是全局的,如果其他文件包含它,它可能对其他程序有用。并且编译器不允许优化掉全局对象。

参考: 如何防止我的“未使用”全局变量被编译出来?

所以,这一切都归功于编译器优化!

于 2013-01-16T13:46:06.153 回答