为什么不需要释放静态数组?

时间:2016-05-10 07:15:00

标签: c scope static return-value lifetime

我想知道为什么静态数组不需要被释放?我知道在创建动态数组时,例如

int *p;
p = malloc(10*sizeof(int));

我们必须使用以下方法释放分配的内存:

free(p);

对于函数中的静态数组,静态数组将在被调用函数完成时自动释放。

我不明白的是:使用如下函数返回静态数组时:

int *subFunc(){
    static int a[5] = {1,2,3,4,5};
    return a;
}

int main(){
    int *p;
    p = subFunc();
}

如果静态数组在完成执行后自动释放,那么我们如何才能正确访问静态数组的值?

5 个答案:

答案 0 :(得分:43)

  

如果静态数组在完成执行后自动释放,那么我们如何才能正确访问静态数组的值?

不,不是那样的。 static变量在开始main()之前被初始化,其生命周期是程序的整个执行。因此,它们可以return来自函数(在其中定义它们)并且仍然可以被访问。它们不是 local (对于函数),当函数完成执行时,它们会超出生命周期。

相关,引自C11,章节§6.2.4

  

在没有存储类说明符的情况下声明其标识符的对象   _Thread_local,可以是外部或内部链接,也可以是存储类   说明符static具有静态存储持续时间。它的一生就是整个执行   在程序启动之前,程序及其存储的值只初始化一次。

关于函数内static变量的范围,是的,它仅限于函数本身,如章节§6.2.1中所述,

  

[...]如果是声明符或类型说明符   声明标识符出现在块内或参数声明列表中   一个函数定义,标识符有块作用域,它终止于   相关块。 [...]

这意味着,显然,您不能在a之外使用数组subFunc(),因为asubFunc()之外不是可见

然而,当你return数组时(返回数组会导致指向数组第一个元素FWIW的指针衰减),因为static数组的生命周期是整个执行该程序,访问返回的指针(当然,在界限内)是完全有效和合法的。

答案 1 :(得分:21)

  

即使在它们所在的块之后,静态变量仍然存在   定义终止。因此,一个静态变量的值   函数在重复函数调用之间保留相同   功能。静态自动变量的范围与此相同   自动变量,即它是它所在的块的本地变量   定义;但是,分配的存储成为永久存储   计划的持续时间。静态变量可以在它们中初始化   声明;但是,初始化器必须是常量表达式,   并且在内存编译时只在编译时进行一次初始化   分配给静态变量。 - source

当控件来自该函数时,不会释放静态数组或变量。静态变量的范围是声明它的函数的局部变量,但它的生命周期是整个程序。

答案 2 :(得分:10)

  

对于子函数中的静态数组,当被调用的子函数完成时,静态数组将自动释放。

事实并非如此。输入函数时不会创建静态数组,并且在离开时不会销毁它们。

静态变量及其中的数据真的很像全局变量!该函数的唯一本地功能是名称。 (你会听到人们谈论变量的范围"这意味着"我在哪里可以使用该名称来引用它。")

因此,当您考虑静态数组的生命时,您可以在心理上取代:

int *subFunc(){
    static int a[5] = {1,2,3,4,5};
    return a;
}

int ONLY_USE_ME_INSIDE_SUBFUNC__a[5] = {1,2,3,4,5};  /* global variable */

int *subFunc(){
    int * a = ONLY_USE_ME_INSIDE_SUBFUNC__a;  /* a is the same as the global */
    return a;
}

然后假装程序中没有其他人可以触及该全局变量。

答案 3 :(得分:3)

  

我想知道为什么不需要释放静态数组?

  1. 无论内存管理功能(malloc,calloc)没有分配什么,例如int a[5]都不需要明确地处理释放

    < / LI>
  2. 静态变量(例如static int a[5])可在本地范围内访问(它们在后续本地函数调用之间保留其值)。它们是在编译时完全为此目的创建的,它们具有程序生命周期,因此即使可能,不是也不会将它们释放出来。

  3. 在其他答案中,其他所有内容都得到了巧妙的解释。

答案 4 :(得分:2)

函数内部的

Static variables,通常用于通过多次调用来维护函数范围内的某些数据。它们在main()之前初始化,它们的生命周期是整个程序执行。因此,如果在退出函数后释放它们就没有意义。如果你释放它们,你将在下次调用函数时崩溃,因为它们不会被引用。