为啥不需要释放静态数组?
Posted
技术标签:
【中文标题】为啥不需要释放静态数组?【英文标题】:Why don't static arrays need to be freed?为什么不需要释放静态数组? 【发布时间】:2016-09-05 00:37:49 【问题描述】:我想知道为什么不需要释放静态数组?我知道在创建动态数组时,例如
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();
如果静态数组在执行完成后自动释放,那我们怎么还能正确访问静态数组的值呢?
【问题讨论】:
【参考方案1】:如果静态数组在执行完成后自动释放,那我们怎么还能正确访问静态数组的值呢?
不,不是那样的。 static
变量在启动 main()
之前被初始化,它的生命周期是程序的整个执行过程。因此,它们可以从函数(在其中定义它们)中return
ed,并且仍然可以访问。它们不是本地(对函数而言),当函数完成执行时,它们的生命周期就会结束。
相关,引自C11
,第 6.2.4 章
一个对象,其标识符在没有存储类说明符的情况下声明
_Thread_local
,可以使用外部或内部链接,也可以使用存储类 说明符static
,具有静态存储持续时间。它的生命周期是整个执行 程序及其存储的值仅在程序启动之前初始化一次。
关于函数内static
变量的范围,是的,它仅限于函数本身,如第 6.2.1 章所述,
[...] 如果声明符或类型说明符 声明标识符出现在块内或参数声明列表中 一个函数定义,标识符有块作用域,它终止于 关联块。 [...]
这意味着,很明显,您不能在subFunc()
之外使用数组a
,因为a
在subFunc()
之外可见。
但是,当您 return
数组时(返回数组会导致指向数组第一个元素的指针衰减,FWIW),因为 static
数组的生命周期是程序的整个执行,访问返回的指针(当然,在界限内)是完全有效和合法的。
【讨论】:
static
locals 的行为与static
globals 有点不同:它们不是在程序启动时初始化,而是when execution first passes their initialization point。
@Quentin 你确定 C 也是如此吗?你能链接一些参考资料吗?
显然我确实混淆了 C 和 C++ 规则。我的坏!
@Quentin @Sourav 不过没关系,在到达初始化点之前,您无法访问函数本地 static
。而在 C 中,static
初始化程序可能无论如何都没有副作用,因此您无法真正观察到它何时被初始化。
您不能在subFunc()
之外使用a
,但我看不出有任何理由您不能使用指向a
的指针并在subFunc()
之外使用它。【参考方案2】:
静态变量即使在它们所在的块之后仍然存在 被定义终止。因此,一个静态变量的值 函数在重复的函数调用之间保留 功能。静态自动变量的范围与此相同 自动变量,即它是它所在的块的本地变量 定义;但是,分配的存储空间对于 程序的持续时间。静态变量可以在它们的 声明;但是,初始化程序必须是常量表达式, 并且初始化只在编译时完成一次,当内存是 分配给静态变量。 - source
当控制来自该函数时,不会释放静态数组或变量。
静态变量的作用域对于声明它的函数是局部的,但它的生命周期是贯穿整个程序的。
【讨论】:
就在今天我听到有人说“不管是在函数内部,静态变量是永远的”。 @Agostino 当然,由于并非所有静态变量都被立即销毁,显然其中一些变量的 forever 值比其他变量更大。 :-)【参考方案3】:并且对于子函数中的静态数组,静态数组会在调用的子函数完成后自动释放。
那不是真的。进入函数时不创建静态数组,离开时不销毁。
一个静态变量,以及其中的数据,真的很像一个全局变量!函数的唯一本地是 name。 (你会听到人们谈论变量的“范围”——这意味着“我可以在哪里使用名称来引用它。”)
所以当你在思考静态数组的寿命时,你可以在脑海中替换:
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;
然后假装程序中没有其他人可以触及该全局变量。
【讨论】:
顺便说一句,一些编译器会将前者视为后者,但使用自动生成的名称,如$STATIC$fd91a2e7$subFunc_a
可以保证不会与 C 文件中有效的任何内容冲突 [因为用户标识符不能包含美元符号]。【参考方案4】:
Static variables
在函数内部,通常用于在多次调用函数时维护函数范围内的一些数据。它们在 main() 之前初始化,它们的生命周期是程序的整个执行。因此,如果它们在退出函数后被释放,那将没有意义。如果你释放它们,你会在下次调用函数时崩溃,因为它们不会被引用。
【讨论】:
【参考方案5】:我想知道为什么不需要释放静态数组?
任何未被内存管理函数(malloc、calloc)分配的东西,例如int a[5]
,对于释放都不需要明确处理。
静态变量,例如static int a[5]
可在本地范围内访问(它们在本地函数的后续调用之间保留其值)。它们正是为此目的在编译时创建的,它们具有程序生命周期,因此即使有可能,释放它们也不是合乎逻辑的考虑,这是不可能的。
其他答案都在巧妙地解释其他所有内容。
【讨论】:
以上是关于为啥不需要释放静态数组?的主要内容,如果未能解决你的问题,请参考以下文章
为啥在 Objective-C 中执行 alloc 和 init 在单独的语句中会导致对象根据 Xcode 静态分析器被释放?