9

块作用域中的 static 关键字与使用 malloc 相比有什么优势?

例如:

功能一:

f() {
    static int x = 7;
}

功能 B:

f() {
    int *x = malloc(sizeof(int));
    if (x != NULL)
        *x = 7;
}

如果我理解正确,这两个程序都会创建一个整数 7 存储在堆上。在 A 中,变量在一开始就在某个永久存储中创建,在 main 方法执行之前。在 B 中,一旦调用函数,您就在现场分配内存,然后在该指针指向的位置存储 7。在哪种情况下,您可能会使用一种方法而不是另一种方法?我知道你不能释放函数 A 中的 x,所以这不会让 B 通常更可取吗?

4

7 回答 7

7

两个程序都创建一个integer 7存储在堆上的

不,他们没有。
static创建一个具有静态存储持续时间的对象,该对象在程序的整个生命周期内保持活动状态。虽然动态分配的对象(由 创建malloc)保留在内存中,直到被显式删除free。两者都提供不同的功能。static在函数调用中维护对象的状态,而动态分配的对象则不然。

在哪种情况下,您可能会使用一种方法而不是另一种方法?

当您static希望对象在程序的整个生命周期内保持活动状态并在函数调用中保持其状态时使用。如果您在多线程环境中工作,static则所有线程都将共享同一个对象,因此需要同步。

当您malloc明确想要控制对象的生命周期时使用。例如:确保对象的生命周期足够长,直到函数调用者在函数调用后访问它。(一旦函数范围内,自动/本地对象将被释放{ }结束)。除非调用者显式调用free分配的内存,否则会泄漏,直到操作系统在程序退出时回收它。

于 2013-03-06T04:06:30.113 回答
0

在函数 A 中,您x使用静态存储持续时间进行分配,这通常意味着它不在(大多数人认为的)堆上。相反,它只是保证在程序运行的整个过程中都存在的内存。

在函数 B 中,您每次进入函数时都会分配存储空间,然后(除非free您没有显示)泄漏该内存。

只有这两个选择,函数 A 显然更可取。它有缺点(尤其是面对多线程),但至少在某些情况下它是正确的。功能 B(就目前而言)是完全错误的。

于 2013-03-06T04:07:16.280 回答
0

忘记堆栈与堆。这不是这里发生的最重要的事情。

有时会static修改作用域,有时会修改生命周期。原型示例:

void int foo() {
     static int count = 0;
     return count++;
}

尝试重复调用它,甚至可能从几个不同的函数或文件中调用,你会看到它count不断增加,因为在这种情况下static,变量的生命周期等于整个程序执行的生命周期。

于 2013-03-06T04:07:57.400 回答
0

如果我理解正确,这两个程序都会创建一个整数 7 存储在堆上

不,静态变量是在 Data 或 BSS 段中创建的,它们在程序的整个生命周期中都有生命周期。当你分配 usingmalloc()时,内存是在堆中分配的,并且必须使用free()call 显式释放它们。

在哪种情况下,您可能会使用一种方法而不是另一种方法?

好吧,当您想要访问同一个变量以多次调用同一个函数时,您使用第一种方法。即,在您的示例中, x 只会初始化一次,并且当您第二次调用该方法时,将x使用相同的变量。

可以使用第二种方法,当你不想为函数的多次调用共享变量,从而第二次调用这个函数时,malloc再次编辑x。你必须每次都释放 x。

您可以通过调用f()2 次来查看差异,对于每种f()

...
f();
f();
...

f(){
    static int x = 7;
    printf("x is : %d", x++);
}

f(){
   int *x = malloc(sizeof(int));
   if (x != NULL)
      *x = 7; 
   printf("x is : %d", (*x)++);
   free(x);   //never forget this,
}

结果会有所不同

于 2013-03-06T04:08:34.450 回答
0

阅读http://www.teigfam.net/oyvind/pub/notes/09_ANSI_C_static_vs_malloc.html

静态变量是在 main() 之前创建的,运行程序后不需要分配内存。

于 2013-03-06T04:12:23.293 回答
0

首先,static 是一个存储类,malloc() 是一个 API,它会触发 brk() 系统调用以在堆上分配内存。

如果我理解正确,这两个程序都会创建一个存储在堆上的整数 7 吗?

否。静态变量存储在分配给程序的内存的数据部分中。即使静态变量的作用域结束,它仍然可以在其作用域之外被访问,这可能表明数据段的内容具有独立于作用域的生命周期。

在哪种情况下,您可能会使用一种方法而不是另一种方法?

如果您想在给定范围内对内存使用进行更多控制,malloc()/free()否则更简单(更清洁)的方法是使用静态。

在性能方面,声明一个静态变量比在堆上分配它要快得多。因为堆管理的算法很复杂,并且处理堆请求所需的时间取决于算法的类型

我能想到建议使用静态的另一个原因是,静态变量默认初始化为零,因此无需担心。

于 2013-03-06T04:19:15.333 回答
0

考虑下面的例子来了解静态是如何工作的。通常我们使用 static 关键字来定义变量或函数的范围。例如,定义为静态的变量将被限制在函数内,并将零售其值。

但是如下面的示例程序所示,如果您将静态变量的引用传递给任何其他函数,您仍然可以从任何其他函数更新相同的变量。

但恰恰是静态变量在程序终止时死亡,这意味着内存将被释放。

#include <stdio.h>

void f2(int *j)
{
    (*j)++;
    printf("%d\n", *j);
}

void f1()
{   
    static int i = 10;
    printf("%d\n", i);
    f2(&i);
    printf("%d\n", i);  
}

int main()
{
    f1();       
    return 0;   
}

但是在 malloc() 的情况下,程序终止时不会释放内存,除非程序员在程序终止之前使用 free() 来释放内存。

这样你会觉得使用 malloc() 我们可以控制变量的寿命,但要注意......当你选择动态内存分配时,你必须非常精确地分配和释放内存。如果您忘记释放内存并且程序终止,则该部分堆不能用于其他进程分配内存。这可能会导致现实世界中的内存不足并减慢计算速度。要摆脱这种情况,您必须手动重新启动系统。

于 2013-03-06T06:07:01.950 回答