gcc 4.6.2 c89
我只是想知道什么可能导致更多的内存问题。例如,如果在堆栈上分配结构数组,或者如果要在堆上动态分配它。
通常,我遵循一个简单的规则。如果只在该函数中使用该结构,那么我在堆栈上进行分配。但是,如果我需要通过将其保存在内存中而将其引用到其他地方,我会动态分配。
我问这个问题的原因是我的一些内存被破坏了,我被告知我应该动态分配而不是堆栈上的结构数组。堆栈内存有更多机会被破坏。但是,如果动态分配的内存损坏,您可以轻松释放它。
上述内容对任何人都有意义吗?
非常感谢任何建议,
答案 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并让函数的调用者去做。
希望它有所帮助。