声明一个数组中间函数是不好的做法

时间:2010-06-07 22:59:00

标签: c

努力只询问我在这里真正想要的东西...我真的只关心是否认为不好的做法或者不要在下面声明一个大小可能不同的数组。如果是......我通常会使用malloc()。

void MyFunction()
{

    int size;

    //do a bunch of stuff
    size = 10; //but could have been something else
    int array[size];

    //do more stuff...

}

5 个答案:

答案 0 :(得分:2)

通常是的,这是不好的做法,尽管新标准允许您使用此语法。在我看来,你必须在(在堆上)分配你想要使用的内存,并在完成后释放它。由于没有可移植的方法来检查堆栈是否足以容纳该数组,因此您应该使用一些可以真正检查的方法 - 例如malloc / calloc&自由。在嵌入式世界中,堆栈大小可能是个问题。

如果您担心碎片,可以创建自己的内存分配器,但这是一个完全不同的故事。

答案 1 :(得分:1)

对于你的问题,我认为每个都有其优点和缺点。

动态分配:
慢,但是你可以通过检查指针来检测何时没有内存给你的程序员。

堆栈分配:
只有在C99中它才会非常快,但是在堆栈溢出的情况下你运气不好。

总之,当您需要一个小数组时,请将其保留在堆栈中。否则,明智地使用动态内存。

答案 2 :(得分:1)

这取决于。第一个显然不是我称之为“正确的”,第二个只是在相当有限的情况下。

在第一个中,你不应该从C中malloc转换 - 这样做可以掩盖意外省略包含正确标题(<stdlib.h>)的错误。

在第二种情况下,您将代码限制为C99或gcc扩展名。只要你知道这一点,并且它适用于你的目的,它就可以了,但几乎不是我称之为便携性的理想。

至于你真正要问的是:上面提到的小错误已经修复,第一个是可移植的,但可能比你想要的慢。如果第二个便携式足以满足您的需要,它通常会更快。

答案 3 :(得分:1)

反对VLA的论点运行,因为堆栈溢出的绝对不好,当你做足够的思考/检查以确保它们安全时,你已经做了足够的思考/检查以使用固定大小的数组:

1)为了安全使用VLA,您必须知道有足够的堆栈可用。

2)在绝大多数情况下,你知道有足够堆栈的方式是你知道size所需的上限,你知道(或者至少愿意猜测或要求)可用堆栈的下限,一个小于另一个。所以只需使用固定大小的数组。

3)绝大多数情况并非如此简单,你使用的是多个VLA(每次调用递归函数时可能只有一个),并且你知道总数的上限大小,小于可用堆栈的下限。因此,您可以使用固定大小的数组,并根据需要将其分成几部分。

4)如果您遇到其中一个案例,在malloc的表现不可接受的情况下,请告诉我......

从源代码的POV开始,使用VLA可能更方便。例如,您可以使用sizeof(在定义范围内)而不是在变量中维护大小,并且将数组划分为块的业务可能需要传递额外的参数。因此,方便的时候会有一些小的收获。

如果您使用大量的堆叠,产生未定义的行为,如果不是一个看起来很可怕的int buf[1920*1024]int buf[MAX_IMG_SIZE],那么您也会更容易错过int buf[img->size] 。这在第一次实际处理大图像时效果很好。这通常是正确测试的问题,但如果您错过了一些可能的困难输入,那么它将不会是第一个或最后一个测试套件。我发现一个固定大小的数组提醒我要么对输入进行固定大小的检查,要么用动态分配替换它,并且不要担心它是否适合堆栈。没有有效的选项可以将它放在堆栈上,担心它是否适合......

答案 4 :(得分:0)

从UNIX / C的角度来看两点 -

当你强制它调用brk()时,malloc很慢。合理数组的含义与为变量分配堆栈空间相同。顺便说一句,当你使用方法#2(通过alloca和我见过的代码libc)时,也会调用brk()来获取大对象。所以这是洗。注意:#2&amp; #1你仍然需要直接或间接调用memset类型的调用来将数组中的字节归零。这只是真实问题(IMO)的旁注:

真正的问题是内存泄漏。当函数重新运行时,alloca会自行清理,因此#2不太可能导致问题。使用malloc / calloc,你必须调用free()或者开始泄漏。