【问题标题】:Written memory when returning from function [duplicate]从函数返回时写入内存[重复]
【发布时间】:2013-12-29 19:31:56
【问题描述】:

我想知道下面这段代码,它非常简单,但是:

char* foo()
{
    int i;
    char buff[100];
    snprintf(buff,100,"This is now written in the stack allocated memory!");

    return buff;   
}

现在,buff 被分配在函数的堆栈中,这意味着每个变量都在 释放了,而我们所拥有的是内存泄漏。 但是在已经写好的位置到底发生了什么?

这些行还是写在内存里的,不是吗?

  • 我可以读取那段内存吗?我确实有指向段开头的指针,如果是这样,它会是这样的:

    char* bar = foo();
    char foobar = bar[0];
    
  • 我可以写信到那个特定的位置吗?类似的例子:

    char* bar = foo();
    bar[1] = 'i';
    
  • 一般来说,为什么它被认为是内存泄漏?我们不能重新分配这个位置吗?

希望得到有关此问题的澄清!

【问题讨论】:

  • 内存泄漏是指您分配内存而没有再次释放它,这将导致您最终耗尽内存。

标签: c++ c memory-leaks heap-memory stack-memory


【解决方案1】:

这不是内存泄漏。它是一个悬空指针。 foo() 返回一个指向不再分配的内存的指针。尝试使用此指针从内存中写入或读取是未定义的行为。

内存泄漏是指您分配的内存不再可访问。例如:

void foo()
{
   char *buff = malloc(10);
}

已经分配了 10 个字节,但永远无法释放这 10 个字节。

在您的情况下,您遇到了相反的问题。您有一个指向因超出范围而自动释放的内存的指针。以这种方式释放内存后,您将无法再尝试以任何方式访问它。

【讨论】:

  • 但是我们仍然知道这些行的确切位置,对吧?这是返回的指针......并且这些行仍然存在。为什么我们不能只阅读它们?
  • @Itzik984:线条可能还在,也可能不在。它是未定义的。
  • 当您从该函数返回时,分配数组的堆栈会折叠到调用该函数之前的大小,因此此时,指针指向堆栈之外的某个位置。
  • 您的程序可能会被中断。任何中断都可能重用自动释放的内存。
【解决方案2】:

从虚拟内存的角度来看,只要您以一种受控方式进行操作,您就可以根据需要对堆栈进行读写,而您的编译器会帮助您。但是,当函数返回时,您告诉编译器用于左堆栈帧的内存可能用于其他数据。阅读:您可能会得到超出您预期的其他数据。写入:您可以覆盖其他数据。

返回时,内存不需要发生任何事情。它可能会保持其当前状态,直到下一次函数调用。 尝试使用调试器检查堆栈。然后你就会知道会发生什么。另外,看看汇编代码。

另见:Can a local variable's memory be accessed outside its scope?

【讨论】:

    【解决方案3】:

    魔术被称为未定义的行为:您正在返回一个指向本地对象的指针。查看此指针指向的内容会导致未定义的行为。任何事情都有可能发生。 This page 试图强调为什么未定义的行为是不好的。

    【讨论】:

      【解决方案4】:

      简单来说,内存泄漏并非如此。问题是您正在返回指向局部变量的指针。您不能返回指向自动局部变量的指针。 buff 是一个自动局部变量,在foo 返回后不再存在,因此指向它的指针无效。
      在用-WallWextra 编译这样的代码时,编译器应该给你警告

      function returns address of local variable
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2018-07-09
        • 2017-01-31
        • 1970-01-01
        • 2020-09-21
        • 2021-08-15
        • 2018-10-18
        相关资源
        最近更新 更多