【问题标题】:Function destroyed after call [duplicate]调用后函数被破坏[重复]
【发布时间】:2018-11-09 15:53:03
【问题描述】:

因为在函数 f 中,缓冲区引用是否可能丢失?我知道该函数在调用后被销毁,但是如果内存地址保持不变,为什么该内容会丢失?另一个细节,因为这是一个不确定的行为。在函数g中,使用strcpy时,内容不会丢失。我想了解编译器做了什么,想在汇编中对其进行采样。谢天谢地。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

char *f(void) {
      char buffer[7] = "blabla";
      char *ptr = buffer;
      return ptr;
}

char *g(void) {
     char *pt = malloc(20);
     char str[7] = "blabla";
     strcpy(pt,str);
     return pt;
}

void main(void) {
    char *s1 = f();
    puts(s1);
    char *s2 = g();
    puts(s2);

}

【问题讨论】:

  • “功能被破坏”是什么意思? “不确定的行为”== 未定义的行为。
  • 编译器是否不会警告您返回一个指向局部变量的指针(在函数返回后不会继续存在)?
  • 这是一个 C++ 问题的答案,但同样的概念也适用.. 读起来很有趣:):stackoverflow.com/a/6445794/3476780
  • 阅读一下“自动”变量...
  • 为了您自己的利益,配置 gcc 以报告所有警告并将它们报告为错误 (-Wall -Werror)。你的编译器足够聪明prevent you from even running this

标签: c gcc


【解决方案1】:

g 中的缓冲区将在对 g 的调用终止后保留,因为它是在堆上分配的。

f 中的缓冲区是在堆栈上分配的(因为它是在没有 static 限定符的情况下声明的,这会将它放在进程的数据部分中),因此它将不再被明确定义为尝试访问当指针超出范围时(即函数退出时),通过指针;返回值将是一个悬空指针。

编译您的代码时收到以下警告:

warning C4172: returning address of local variable or temporary: buffer

【讨论】:

  • 是的,但我确实在这里编译并且都显示了更改的内容。怎么可能。如果缓冲函数是局部变量?行为总是在变化,我想知道为什么。
  • @Yuri 未定义行为意味着任何事情都可能发生。这包括有时有效,有时无效。
  • @Yuri 您可以检查编译器生成的汇编代码,或者通过调试器逐步运行可执行文件以查看发生了什么。
  • @GovindParmar 只是为了向未来的读者澄清:在函数中声明的变量会进入堆栈,除非它们具有静态限定符,然后它们会进入数据段。为什么当你把 static 放在前面时它会起作用并不是因为它是一个使堆栈地址保持不变的魔术词,而是它改变了变量在程序内存中的位置,使其不再在堆栈上。
  • @Bwebb 你是对的;我会尽快更新我的帖子以明确澄清这一点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-04-07
相关资源
最近更新 更多