【问题标题】:Variable declaration and their memory addresses in CC中的变量声明及其内存地址
【发布时间】:2013-05-10 15:05:15
【问题描述】:

我创建了一个简单的程序:

#include <stdio.h>

int main()
{
    int s1;
    int s2;
    int s3;
    
    int *p1, *p2, *p3;
    
    p1 = &s1;
    p2 = &s2;
    p3 = &s3;
    
    printf("%d\n%d\n%d", p1, p2, p3);
}

每当我运行这个程序时,它都会打印指针p1p2p3的内存地址,有趣的是这些值有12的差异。我想知道这背后的原因。为什么地址与12 不同?

注意:每次我执行程序都会发生这种情况。

输出:


我在许多类型的变量中测试了同一个程序,我得到的结果是..

当变量是 char 类型时。


当变量是长类型时


当我声明 int array 时,每个数组的大小为 1。


当第二个声明数组的大小为 2 时,它会获得额外的 4 字节偏移量。

【问题讨论】:

  • 为什么不使用为打印指针设计的格式说明符,或者更好的是std::cout?为什么不对main 使用有效签名?
  • 这是什么编译器和平台?
  • 这取决于编译器,就像每个人都说的那样。编译器可能已经把任何东西放在它想要的任何地方。您可能不会在发布版本中看到它。这些变量之间可能存在调试信息,可能是某种溢出检测或某些功能,例如 MSVC 在调试时进行的即时编译。您可以通过查看反汇编来查看其中的任何内容。
  • 我猜是,由于分配的顺序,编译器选择交错intint* 值,并且您在64位平台上。每个int 4 个字节,每个int* 8 个字节。但正如人们所说,看反汇编。
  • 我认为您还应该了解correct signatures for main 以及为什么void main is bad

标签: c visual-c++ pointers memory


【解决方案1】:

我猜这是一个调试版本。我已经尝试过使用 Visual Studio 2010 构建的这个程序。在调试时,地址之间有 12 个字节的差异。在发布模式下,有 4 个字节 (sizeof(int)) 的差异。

在调试版本中,MSVC 编译器添加了额外的数据来帮助检测缓冲区溢出和未初始化内存的使用。如果在printf 语句上设置断点并查看p1 指向的内存,您应该会在内存中看到cc

内存初始化为许多不同的魔法值。 cccccccc 表示未初始化的堆栈空间。如需更详细的列表,请参阅此问题的答案:In Visual Studio C++, what are the memory allocation representations?

【讨论】:

    【解决方案2】:

    我很确定这是“编译器会在您不应该写入的地方添加额外的东西以检测您何时写入”的情况。 Micrsoft 确实喜欢这样做,以便它可以检测到您的代码何时做坏事。尝试类似:

    void func()
    {
      int x = 18;
      int *px = &x;
      px[1] = 4711;
      cout << "px = " << px << " x = " << x << " px[1] = " << px[1] << endl;
    }
    

    看看编译器是否没有“检测到”这段代码在做坏事......如果是,那是因为它在 x 和 p 之间放置了“填充”,并检查函数何时返回那些“ padding”区域没有被触及。

    【讨论】:

    • gcc -g -O0 -Wall -fstack-protector-all -Wstack-protector op_code.c -o a.out 确实给出了 4 个字节的偏移量什么保护窗口有哪些 gcc 没有??
    • @0x90(或者我应该叫你 NOP?):其中一个 cmets 说 OP 使用的是 Visual Studio 2008,所以不使用 gcc。
    • 我知道这就是为什么我问微软的编译器知道做什么 GCC 不知道? :)
    • @0x90 AFAIK 这些是 gcc 中的安全堆栈保护标志(例如堆栈金丝雀)。在这种情况下,MSCV 编译器正在添加信息以帮助调试和错误报告。它仅出现在调试版本中,而不出现在发布版本中。它们与安全保护无关。
    • @0x90 恐怕我对gcc 的了解有限。但据我所知,-g 标志添加了调试符号,因此您可以在调试器中看到某种级别的代码,而不是汇编程序。它不会更改代码。 stackoverflow.com/questions/4884535/…
    猜你喜欢
    • 2011-07-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-09
    • 2018-04-21
    • 1970-01-01
    • 1970-01-01
    • 2012-09-08
    相关资源
    最近更新 更多