【问题标题】:Pointer pointing to itself C指向自身的指针 C
【发布时间】:2016-02-14 13:22:08
【问题描述】:

我正在编写一个在递归链末尾调用的函数。这个函数需要在它被调用的实例中找出它在内存中的位置。代码如下:

void recover ()
{
     int * x = (int *)&x;
}

问题是程序只是跳过了这个语句,就好像它从来没有写过一样。我已经在 GDP 中验证了这一点。你能想到为什么这条线被忽略了吗?

谢谢!

【问题讨论】:

  • 你希望这个语句做什么?如所写,该函数什么都不做,这就是您所看到的。任何半体面的编译器都会优化整个函数。
  • printf("Function at address: 0x%x\n", recover);
  • 嗯,我需要这个内存地址,这样我就可以在 GDP 中访问它,并有效地使用它来回溯以前的函数调用。我的最终目标是找到传递给函数 foo 的原始参数,其中调用了 recover()
  • 您可以切换到汇编视图并检查寄存器,虽然我不熟悉 GDP 功能。
  • 你说的这个GDP是多少?你确定你实际上不是指 gdb 吗?在这种情况下,您只需查看 esp(或 x86_64 上的 rsp)即可查看您在堆栈中的位置 - 更简单地说,bt 将向您显示调用者所有参数的值。此外,将变量标记为volatile 可以保护它免受优化器的影响。但更一般地说,你想用所有这些东西来实现什么?请记住,涉足堆栈都是 UB。

标签: c pointers


【解决方案1】:

将变量声明为volatile。它应该防止编译器优化。

volatile int * x = (int *)&x;

【讨论】:

    【解决方案2】:

    如果您在打开优化的情况下进行编译,那么这段代码可能由于对程序没有影响而被优化掉了。使用-O0 选项。

    【讨论】:

      【解决方案3】:

      您编写的代码可能是未定义的行为,因为您将指向int的指针转换为指向int的指针

      指针在概念上不能指向自身,因为您永远无法实现正确的间接级别。原因如下:

      Declaration      |  Type     | Type after using the & operator
      --------------------------------------------------------------
      int   x;         |  int      | &x is an (int*)
      int*  x;         |  int *    | &x is an (int**)
      int** x;         |  int **   | &x is an (int***)
      

      但是,void* 是我能想到的唯一一种可能被允许违反此规则的指针类型,但我不确定根据标准它是否合法。

      我建议你写以下内容,而不是你所拥有的:

      int* recover ()
      {
          int local = 0;
          return &local;
      }
      

      并在没有像 @ysap 建议的优化的情况下编译它。

      仍然从您的示例中,您似乎正在尝试找出堆栈顶部的位置,而这在汇编中很容易完成。您需要做的就是读取堆栈指针。但是,这在 C 中并没有那么清楚地公开。虽然 GCC 确实有一些 helper functions 用于类似任务,但我还没有找到堆栈指针。

      我个人会求助于内联汇编,因为无论如何编写的任何内容都可能无法移植。

      此外,如果我正确理解您的问题,它很可能与 this question 重复,因此阅读这些答案也是值得的。

      编辑:应该相当于返回当前函数的frame的地址,可以使用GCC builtin function __builtin_frame_address (unsigned int level) linked earlier来完成。代码如下所示:

      int* recover()
      {
          return (int*)__builtin_frame_address(0);
      }
      

      【讨论】:

      • 当你尊重它时,分配一个指向错误指针类型的指针不是未定义吗?
      • 我不确定这就是为什么我说“可能”。如果你有参考,我很乐意改变我的说法。
      猜你喜欢
      • 2021-09-21
      • 2014-08-16
      • 1970-01-01
      • 2021-12-31
      • 1970-01-01
      • 2010-12-02
      • 1970-01-01
      • 2019-09-10
      • 1970-01-01
      相关资源
      最近更新 更多