【问题标题】:C language variable in executable file可执行文件中的 C 语言变量
【发布时间】:2018-09-22 04:12:31
【问题描述】:

像下面这样简单地编写 C 文件:

int main()
{
    int a = 999;
    return 0;
}

使用gcc编译链接后,会生成一个可执行文件(如.exe、.out)

但是当我用一些编辑器打开(不运行)可执行文件时,我找不到变量“a”的值,即数字 999,十六进制为 0x3E7。

我的问题是:

  • 变量号999是否存在于可执行文件中?
  • 如果不是,变量号存储在哪里?运行中的可执行文件如何获取变量号?

P.S:我对 .data .bss .text .etc 和汇编语言等内存部分有一点了解。甚至我使用 ollydbg 都找不到。

【问题讨论】:

  • 您是否在编译时进行了优化?
  • @Michael Petch 我使用 gcc -O1 a.c
  • 这就是原因。通过对编译器进行优化(即使使用-O1),编译器已经确定,由于您创建了一个从未使用过的变量,因此它可以完全删除它。尝试在没有优化的情况下构建 (-O0)。
  • 如果我是你,我会将 C 代码编译为程序集(选项 -S)。然后我会查看 gcc 生成的汇编文件。
  • 如果曾经存储在可执行文件中,在 little-endian 上不会是 0xE7 0x03 吗?

标签: c gcc assembly exe compiler-optimization


【解决方案1】:

编译器没有理由将值999 放在任何地方,因为它不会在任何地方使用。无论999 是否在内存中,该程序都具有相同的可观察行为。

ISO/IEC 9899:TC2 - 5.1.2.3 程序执行:

  1. 在抽象机中,所有表达式都按照语义的规定进行评估。 如果一个实际的实现可以推断出它的值没有被使用并且没有产生所需的副作用,则不需要评估表达式的一部分(包括由调用函数或访问易失性对象引起的任何副作用)。

【讨论】:

    【解决方案2】:

    优化的一个重要功能是删除未使用的东西。程序的行为完全不依赖于999,并且a 不是volatile,因此赋值不是任何可见副作用的一部分,并且程序完全等同于@ 987654326@

    以 asm 形式查看编译器输出要容易得多。

    在 Godbolt 编译器资源管理器中,您可以对其进行设置,以便在不同的窗格中同时查看 gcc -O0gcc -O1 的 asm 输出。 https://godbolt.org/z/wNHEnN.

    mov DWORD PTR [rbp-4], 999 位于-O0,以及堆栈帧设置绒毛。因此-O0 输出将999 作为mov 指令的双字立即操作数。该变量是本地变量,因此您不会在 .data.rdata 部分中找到它的符号表条目(就像使用带有静态初始化程序的全局变量一样)。

    有关查看编译器输出的更多信息,另请参阅 How to remove "noise" from GCC/clang assembly output?

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-11-28
      • 2022-12-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-26
      • 1970-01-01
      相关资源
      最近更新 更多