【问题标题】:Memory allocation order in c++c++中的内存分配顺序
【发布时间】:2011-01-25 11:08:29
【问题描述】:

我编写了以下代码,试图解决一个请求类似数组的结构而不使用它们的挑战:

#include <iostream>

int main(){
    int x = 132,y = 33,z = 87;

    int *i = &x;

    std::cout << x << " " << y << " " << z << "\n";
    std::cout << &x << " " << &y << " " << &z << "\n";
    std::cout << i << " " << i-1 << " " << i-2 << "\n";
    std::cout << *i << " " << *(i-1) << " " << *(i-2) << "\n";   
}

我发现 2 个变量的地址 (&y-&x) 之间的差异为 -1,我随后修改了代码 我不明白为什么最后一个定义的变量是在“之前”分配的(意思是以前的地址)。

老实说,我会认为 &y-&x = 1。

你能给我一些建议吗? (没有双关语:P) 哦,我知道代码是不好的做法 - 但它有缺点或例外吗?

提前谢谢你

【问题讨论】:

  • 您无法对这些局部变量的分配方式、位置或顺序做出任何有效的假设。
  • 我无法假设 &y-&x 等于 &z-&y?
  • 正如我上面所说,你不能对此做出任何有效的假设...

标签: c++ memory pointers


【解决方案1】:

这种做法很糟糕。

未指定堆栈布局;即使变量实际上具有堆栈表示(它可能没有,如果您不获取变量地址并且优化器将其移动到寄存器),变量和填充之间的顺序(即指针之间的差异)未指定。

您可以获得指向局部变量的指针,但不能对其进行指针运算 - 您会得到未定义的行为(当然,除非我们讨论的是局部数组变量)。

最后,至少有一个平台 abs(&y - &x) 永远不会为 1(因为堆栈变量是 16b 对齐的)。

【讨论】:

  • 感谢您的回复。正如我所说,我不能使用数组。我认为没有一种安全的方法可以做到这一点,不是吗?哦,也许更好的方法是 i+(&y-&x) 和 i+2*(&y-&x)。这样代码就不会依赖我的平台了
  • i + (&y - &x) 可能适用于所有实际的编译器,但在技术上仍未定义。 i + 2 * (&y - &x) 在不同的编译器上会失败,具体取决于优化选项和其他因素。
【解决方案2】:

因为堆栈在您的机器上向下增长。有一些有用的图表对 Intel x86 大约半途而废this page

【讨论】:

  • 感谢图表,它们非常适合 intel cpus
  • @framp:@TonyK。这只是对它在概念上如何工作的简单表示。编译器没有这样的受赠者,我怀疑有些系统出于安全原因不这样做。实际上没有任何理由不能像任何其他动态内存一样在堆内动态分配堆栈帧。
  • @Martin York:我根据 OP 的经验水平给出了答案,但我不认为我过于简单化了。简化,也许。但是这些“安全原因”是什么?我很怀疑。
  • @TonyK:它是ASLR 的一部分。它不是安全的灵丹妙药。但这让攻击者的事情变得更加困难。
  • @Martin York:这个链接当然很有趣!但是我没有看到任何关于从堆中分配堆栈帧的信息。我还是半信半疑。
【解决方案3】:

编译器可以随意放置变量。在许多当前的操作系统上,堆栈向下增长,因此如果编译器天真地按堆栈顺序分配变量,则稍后声明的变量位于较低的内存位置。但同样,这完全是任意的。

【讨论】:

  • 不仅如此,如果编译器可以优化它,它甚至可能根本不分配变量。
猜你喜欢
  • 2015-10-24
  • 2015-12-28
  • 2023-03-14
  • 1970-01-01
  • 2014-10-25
  • 2010-12-11
  • 2010-11-07
  • 2022-01-21
相关资源
最近更新 更多