堆栈分配的内存与动态分配的内存

时间:2012-01-07 12:41:49

标签: c memory-management

gcc 4.6.2 c89

我只是想知道什么可能导致更多的内存问题。例如,如果在堆栈上分配结构数组,或者如果要在堆上动态分配它。

通常,我遵循一个简单的规则。如果只在该函数中使用该结构,那么我在堆栈上进行分配。但是,如果我需要通过将其保存在内存中而将其引用到其他地方,我会动态分配。

我问这个问题的原因是我的一些内存被破坏了,我被告知我应该动态分配而不是堆栈上的结构数组。堆栈内存有更多机会被破坏。但是,如果动态分配的内存损坏,您可以轻松释放它。

上述内容对任何人都有意义吗?

非常感谢任何建议,

4 个答案:

答案 0 :(得分:4)

通常,永远不要静态分配,而是在数据结构是函数本地时在堆栈上进行分配。这使得创建可重入函数和避免各种问题变得更加容易。

(作为例外,静态分配const数据没有问题。)

编辑:好的,你的意思是堆栈分配。在这种情况下,您遵循的规则是合理的做法。但堆栈和堆分配都不能防止内存损坏。

答案 1 :(得分:3)

我不会说分配结构的任何一种方式都有更多的腐败机会"。无论导致腐败的原因是什么,都可以轻松地分配。

我说你最好修复损坏的来源:你可以使用gdb在使用watch <varname>写入损坏的变量时设置断点。或者,您也可以在检测到损坏时设置断点,然后使用reverse debugging查找损坏发生的位置。


编辑:关于堆栈和static分配的含义似乎有些混乱:

void foo() {
    int a[10]; // stack
    static int b[10]; // static

    int *c = malloc(sizeof(int) * 10); // dynamic on the heap
}

堆栈变量仅在函数的生命周期内有效 - 一旦此函数返回,您就不能期望a位置的数据仍然有效。有时这些被称为本地自动变量。

函数内部的

静态变量在函数外部也是有效的 - 数据在函数调用之间保持不变。这意味着如果你这样做:

void foo() {
    static int a = 0;
    a++;
    printf("%d\n",a);
}

每次调用foo()时,打印的数字将增加1。通常,函数不会将许多变量声明为静态变量,因为静态变量会记住上次调用函数时的最后一个值 - 这通常不是您想要的行为。可能这就是那个告诉你静态变量有更多机会被腐蚀的人的意思。

变量从创建时到有效free()时都有效。这也称为动态分配,如果您计划将数据返回到程序的其他部分(或者如果您想在C89中指定运行时数组的长度),则可以使用它)。


除此之外:static令人困惑的是,当应用于全局范围内的函数名称或变量时:

static void foo() { ... }
static int x;

表示&#34;此功能或变量仅在此翻译单元内可见&#34;。我不确定为什么static关键字有这两种不同的含义。

答案 2 :(得分:3)

如果您担心内存损坏,您应该担心动态和静态分配。如果你有腐败,那么差异只会是被破坏的,但不管怎样,结果都会很糟糕。

如果你担心泄漏,那么静态分配可以简化生活 - 你不需要释放它,所以它不会泄漏。

但我认为主要标准应该是静态分配是否会让你分配太多 通过动态分配,您可以根据实际需求调整分配大小,而使用静态分配,您可能需要分配更多,最多可达到理论最大值。例如,如果您希望每个客户端有一个结构,并且最多支持1000个客户端,则必须提前分配1000个结构,即使实际上只有3个客户端。通过动态分配,您可以在需要时分配所需内容。

答案 3 :(得分:2)

“通常,我遵循一个简单的规则。如果结构仅用于该函数,那么我将静态分配。但是,如果我需要通过将其保留在内存中而在其他地方引用它,我将动态分配。 “

正确,你做得很好。

说明:静态分配内存时,在堆栈/堆/系统在函数内部使用时,该内存将在函数返回之前可用。如果将它传递给另一个函数,它就有效,就好像e。 G。 function_a创建了数组/结构并调用了function_b,function_a还没有返回,所以数组有效。以下是:

int function_b(char *buf); /* whatever it does */

int function_a() {
    char array[30];
    /* fill "array" */
    function_b(array); /* valid as this is yet inside this function */
    return 0;
}

但是当function_a返回时,这个内存被解除分配(这就是为什么你不必担心静态分配的内存:它不是真正静态分配,系统在函数返回后自动释放它) 。因此,以下将是不正确的并且可能导致运行时错误(例如,分段违规或类似):

char *function_a_segfaulty() {
   char array[30];
   do_some_stuff();
   return array; /* INCORRECT: array is now invalid, as the function has returned */
}

当你需要malloc()'缓冲区并返回它时,就是这种情况。 Malloc()向操作系统询问内存并返回与其开头的函数无关指针,因此函数通过并且内存仍然有效。上面的例子必须这样做:

char *function_a_correct() {
   char *array = malloc(30);
   do_some_stuff();
   return array; /* correct */
}

但在这种情况下,你必须考虑释放那个数组。一个常见的做法是记录这个函数的返回值必须是free()'d并让函数的调用者去做。

希望它有所帮助。