首页 > 解决方案 > 从C中的函数返回一个数组

问题描述

我编写了一个返回数组的函数,虽然我知道我应该返回一个动态分配的指针,但我仍然想知道当我返回一个在函数内本地声明的数组时会发生什么(没有将其声明为静态),当我注意到我的函数中的内部数组的内存没有被释放时,我感到很惊讶,我把我的数组放回了main。主要的:

int main()
{
    int* arr_p;
    arr_p = demo(10);

    return 0;
}

和功能:


int* demo(int i)
{
    int arr[10] = { 0 };
    for (int i = 0; i < 10; i++)
    {
        arr[i] = i;
    }
    return arr;
}

当我取消引用时,arr_p我可以看到函数中设置的 0-9 整数demo。两个问题:

  1. 为什么我检查时发现它的地址与函数中arr_p的地址相同?arrdemo
  2. 怎么会demo_p指向尚未释放的数据(0-9 数字)demo?我预计arr内部demo将在我们超出demo范围时被释放。

标签: arrayscmemory-managementscope

解决方案


编程时必须注意的一件事是要注意规则所说的内容,而不仅仅是看起来有效的内容。规则说您不应该返回指向本地分配数组的指针,这是一条真实的规则。

如果您在编写返回指向本地分配数组的指针的程序时没有收到错误,那并不意味着它没问题。(虽然,这意味着你真的应该得到一个更新的编译器,因为任何体面的现代编译器都会对此发出警告。)

如果您编写的程序返回指向本地分配数组的指针并且它似乎可以工作,那也不意味着它没问题。对此要非常小心:通常,在编程中,尤其是在 C 中,看起来可以工作并不能证明您的程序是好的。您真正想要的是让您的程序以正确的理由运行

假设你租了一间公寓。假设,当您的租约到期并且您搬出时,您的房东没有从您那里领取您的钥匙,但也没有更换锁。假设,几天后,你意识到你在一个壁橱的后面忘记了一些东西。假设,你不问,偷偷回来尝试收集它。接下来发生什么?

  • 碰巧的是,您的钥匙仍然可以在锁中使用。这是一个完全的惊喜,还是有点出乎意料,或者保证会奏效?
  • 碰巧的是,您忘记的物品仍然壁橱里。它还没有被清除。这是一个完全的惊喜,还是有点出乎意料,或者保证会发生?
  • 最后,无论是你的老房东,还是警察,都没有因为你的这种侵入行为而与你搭讪。再一次,这是一个完全的惊喜,还是有点出乎意料,或者几乎完全可以预料到?

您需要知道的是,在 C 语言中,重用您不再被允许使用的内存与偷偷溜回您不再租用的公寓非常相似。它可能有效,也可能无效。你的东西可能还在,也可能不在。你可能会遇到麻烦,也可能不会。没有办法预测会发生什么,也没有(有效的)结论可以从发生或没有发生的事情中得出。

回到你的程序:像这样的局部变量arr通常存储在调用堆栈中,这意味着即使在函数返回后它们仍然存在,并且可能不会被覆盖,直到下一个函数被调用并使用堆栈上的那个区域作为它的自己的目的(甚至可能不是)。因此,如果您返回一个指向本地分配内存的指针,并立即取消引用该指针(在调用任何其他函数之前),它至少有点可能“工作”。这又类似于公寓的情况:如果还没有其他人搬进来,那么您忘记的物品很可能仍然在那里。但这显然不是您可以依赖的东西。


推荐阅读