3

我遇到了这个页面,该页面说明了创建悬挂点的常用方法。

下面的代码用于通过返回局部变量的地址来说明悬空指针:

// The pointer pointing to local variable becomes  
// dangling when local variable is static.
#include<stdio.h>

int *fun()
{
    // x is local variable and goes out of scope 
    // after an execution of fun() is over.
    int x = 5;

    return &x;
}

// Driver Code
int main()
{
    int *p = fun();
    fflush(stdout);

    // p points to something which is not valid anymore
    printf("%d", *p);
    return 0;
}

在运行它时,这是我得到的编译器警告(如预期的那样):

 In function 'fun':
12:2: warning: function returns address of local variable [-Wreturn-local-addr]
  return &x;
  ^

这是我得到的输出(到目前为止很好):

32743

但是,当我注释掉 fflush(stdout) 行时,这是我得到的输出(带有相同的编译器警告):

5

这种行为的原因是什么?fflush 命令的存在/不存在究竟是如何导致这种行为变化的?

4

2 回答 2

3

正如您所提到的,返回指向堆栈上对象的指针是不好的。您只看到fflush()调用存在问题的原因是如果堆栈不存在,则堆栈未修改。也就是说,5仍然存在,所以指针取消引用仍然给5你。fun如果您在and之间调用一个函数(可能几乎是任何函数)printf,它几乎肯定会覆盖该堆栈位置,使后面的取消引用返回该函数碰巧离开那里的任何垃圾。

于 2017-04-23T02:18:09.183 回答
0

这是因为调用fflush(stdout)写入到所在的堆栈x

让我解释。汇编语言中的堆栈(所有编程语言最终都以一种或另一种方式运行)通常用于存储局部变量、返回地址和函数参数。当一个函数被调用时,它将这些东西压入堆栈:

  • 函数完成后继续执行代码的地址。
  • 函数的参数,按使用的调用约定确定的顺序。
  • 函数使用的局部变量。

然后,只需更改 CPU 认为堆栈顶部的位置,这些东西就会一一从堆栈中弹出。这意味着数据仍然存在,但不能保证继续存在。

fun()在覆盖堆栈顶部上方的先前值之后调用另一个函数,在这种情况下使用 的值stdout,因此指针的引用值会发生变化。

在不调用另一个函数的情况下,数据会保留在那里,并且在取消引用指针时仍然有效。

于 2017-04-23T02:38:25.217 回答