【问题标题】:stack growth direction堆栈增长方向
【发布时间】:2011-04-04 02:38:39
【问题描述】:

所以从我之前的 memmove 问题中,我想知道如何找到堆栈增长的方向。

  void stackDirection(int* i)
  {

     int j;

     if(&j>i)
         cout<<"Stack is growing up \n"<<endl;
     else 
         cout<<"Stack is growing down \n"<<endl;


   }
  int main()
  {    
      int i=1;

      stackDirtection(&i);

 }

【问题讨论】:

  • 你的代码不起作用,或者问题出在哪里?
  • 问题是我不能说这段代码是否正确
  • imo 更好的测试是顺序 _alloca 调用,因为堆栈指针将位于同一堆栈帧中,并且不会受到任何编译器优化
  • 如果您进行实验,并获得有效且可重复的结果……
  • 同一个函数本身比较两个变量的地址比较好。在 main 本身中,您可以创建 j 变量并比较地址。它应该给出有效的结果。

标签: c++


【解决方案1】:

堆栈可能不会向上或向下。

每个堆栈帧都可能被分配到堆内的随机点。
这实际上是在几个操作系统中完成的,以尝试防止恶意代码破坏堆栈。

堆栈向堆增长的概念只是教授堆栈概念的一种简单方法(当然,早期的实现确实以这种方式工作,因为它很简单(当没有人时,不需要做比你需要的更难的事情)试图打破你))。

【讨论】:

  • @Martin Stack 是在堆上创建的?我明白了吗?操作系统将堆栈与堆分开并将它们分成页面对吗?这怎么可能依赖于架构?因为我在这里指的是正确的逻辑地址,而这些逻辑地址只是依赖于编译器,对吗?
  • @Brett:从硬件的角度来看,所有的内存都只是内存。然后操作系统可以选择做它想做的任何事情。
  • @brett:在过去,堆栈和堆是独立的实体,并且在概念上相互发展。但这很容易被破坏并导致恶意代码执行。所以一些聪明的人有一点想法。现在堆栈只是一系列帧(每个函数调用一个)。没有技术原因他们需要一个接一个地去(因为当前有一个链接回到最后一个)。那么为什么不使用普通的内存管理例程在堆中分配堆栈帧。从概念上讲:展开堆栈是释放当前帧并跟随链返回。
  • @brett:可能比这稍微复杂一些,但从概念上讲,没有理由不能在堆内分配每个堆栈帧。只要函数局部变量在退出局部范围时正确销毁,堆栈的实现细节对执行代码应该没有影响。它是一个经典的 OO 设计(运行时更改了堆栈框架的实现,但代码不需要知道,因为堆栈框架的接口是相同的。唯一受影响的代码是依赖于堆栈的实现细节(比如你的代码))。
  • @Martin York 你能指点我一些文章或一本书来解释我吗
【解决方案2】:

这样的实验是不可靠的,因为您可能会遇到异常。优化器可能会搞砸你,或者系统可能会使用寄存器作为参数。如果您真的必须知道堆栈方向,请阅读您的处理器的手册。

尽管如此,除非您正在编写操作系统或非常低级的东西,否则如果您需要知道堆栈方向,您可能正在做一些丑陋和可怕的事情,并且应该真正重新考虑您的方法。

【讨论】:

    【解决方案3】:

    您的函数依赖于 int* 参数,该参数可以指向任何地方,也可以为 NULL。最好比较两个局部变量的地址。

    【讨论】:

    • 编译器可以任意顺序分配局部变量。是的,它会以正确的顺序构造和销毁它们,但它可以在任何地方为它们分配空间。
    【解决方案4】:

    这超出了 C++ 标准的范围。它是一种实现定义的行为,可能取决于特定的操作系统/处理器架构等。

    最好不要依赖或依赖这些细节,除非你喜欢 ETHICAL hacking :) 和/或不太关心可移植性

    【讨论】:

      【解决方案5】:

      考虑以下重写,它揭示了编译器实现代码的一种方式:

      void stackDirection(int* i) { 结构 __vars_stackDirection { 诠释 j; } *__stackframe_stackDirection = malloc(sizeof(int));

       if(&(__stackframe.j) > i)
           cout<<"Stack is growing up \n"<<endl;
       else 
           cout<<"Stack is growing down \n"<<endl;
      

      } 主函数() {
      结构 __vars_main { 诠释我; } *__stackframe_main = malloc(sizeof(int));

        stackDirection(&(__stackframe.i));
      

      }

      您必须同意__stackframe_stackDirection__stackframe_main 基本上是随机的。堆栈可以向上或向下增长。

      更糟糕的是,您假设的是线性模型。要么a&lt;b, b&lt;a, or a==b。但是对于指针,这不成立。所有三个比较a&lt;b, b&lt;a and a==b 可能同时为假。

      【讨论】:

        猜你喜欢
        • 2011-03-23
        • 2021-12-08
        • 2011-12-28
        • 2012-10-08
        • 2015-02-21
        • 1970-01-01
        • 2012-07-30
        相关资源
        最近更新 更多