【问题标题】:Returning an address of local variable behaviour [duplicate]返回局部变量行为的地址[重复]
【发布时间】:2012-09-07 01:00:12
【问题描述】:

可能重复:
Can a local variable's memory be accessed outside its scope?

输入:

#include <stdlib.h>
#include <stdio.h>
int func2(void);
int* func1(void);

int func2(void)
{
    int* b;
    b = func1();
    printf("%d", *b);
    printf("%d", *b);
    printf("%d", *b);
}

int* func1()
{
    int a = 13;
    return &a;
}

int main()
{
    func2();
}

输出:

13 -1077824828 -1077824828

谁能解释堆栈和操作系统中发生了什么?为什么获取指针的值后结果从13变成垃圾?

【问题讨论】:

  • 重复数字无穷大加一。这是未定义的行为。
  • 此外,func2 没有 return 任何东西,尽管它是用返回类型 int 定义的。
  • 要真正回答这个问题:在您的特定情况下,对printf() 的第一次调用会覆盖从调用func1() 时遗留在堆栈中的13
  • 语言标准未定义。由实现完美定义。

标签: c pointers scope undefined-behavior local-variables


【解决方案1】:

调用 printf 会创建一个新的堆栈帧,该堆栈帧会覆盖之前由 a 占用的位置。

【讨论】:

  • 也许,也许不是。当您调用未定义的行为时,您无法真正从一般意义上推断会发生什么。
  • 当然可以。迪玛是对的。它是完美定义的,但取决于平台。
【解决方案2】:

当然。 调试和发布(干净)的结果会有所不同。 如果您查看程序集,则局部变量是 EBP-(一些偏移量)。 这意味着,HIGHER IN STACK,如“进一步”。

这是您返回的地址。

如果函数只是返回,通常它不会被触及。在某些编译器的调试版本中,它会被故意丢弃以帮助您更快地捕获悬空指针错误。现在, printf 调用重用堆栈中的相同地址来传递参数和它自己的局部变量(它有一些)。它们将被写入 func1 return 清空的地址,从而覆盖您获得的地址所指向的任何内容。

【讨论】:

  • 为什么 printf 会把参数传给栈?它们不是直接发送到标准输出缓冲区吗?
  • 不,它们不是,这很重要:生成调用者代码的编译器一定不知道“printf”是什么意思,尤其是这个函数将要做什么——比如使用标准输出。
猜你喜欢
  • 2021-04-28
  • 2013-01-30
  • 2011-04-13
  • 2023-03-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-05-14
  • 2020-12-30
相关资源
最近更新 更多