在支持可变长度阵列之前,我会像这样动态分配它们:

int foo(size_t n)
{
    int *arr = malloc(n * sizeof int);
    if (!arr) return ENOMEM; /* not enough memory */
    .
    . else do stuff with arr[]
    .
    free(arr);
    return 0;
}

使用可变长度阵列,我现在可以使其看起来更干净:

int bar(size_t n)
{
    int arr[n];
    .
    . do stuff with arr[]
    .
    return 0;
}

现在,我没有“不记忆”检查。实际上,如果n太大,该程序就会崩溃。

如果N太大,我该如何优雅地从Bar(N)保释?

有帮助吗?

解决方案

这种情况与任何其他本地变量完全没有变化 - 这样的声明:

int baz(void)
{
    int arr[100000];
    .
    . do stuff with arr[]
    .
    return 0;
}

有完全相同的问题。 “解决方案”与往常一样 - 不要重新浏览太深,也不要分配具有自动存储时间的非常大的数据结构(继续使用 malloc() 对于这些情况)。 “非常大”的价值在很大程度上取决于您的环境。

换句话说,不要声明 int array[n]; 除非你知道 n 受到一个合理的价值的限制,因此您很乐意将最大大小的数组宣布为普通的,非变化的类型阵列。

(是的,这意味着可变修饰的类型阵列不像它们最初出现的那样有用,因为您只需以最大所需的大小而声明数组,就很少获得。

其他提示

您可以通过不使用它们来防止它们崩溃。 :)

认真地说,除非您对尺寸有强大的界限,否则几乎没有安全的方法来使用可变长度阵列来使您的生活更轻松。另一方面,您可以以这样的方式有条件地使用它们:

char vla_buf[n < 1000 ? n : 1];
char *buf = sizeof vla_buf < n ? malloc(n) : vla_buf;
if (!buf) goto error;
/* ... Do stuff with buf ... */
if (buf != vla_buf) free(buf);

虽然这看起来像是无用的痛苦,但它可以产生巨大的性能差异,尤其是在许多呼叫的螺纹应用程序中 mallocfree 可能导致锁定。 (此技巧的一个值得注意的辅助优势是,您可以通过简单地替换VLAS支持旧编译器 [n < 1000 ? n : 1]1000, ,例如用宏。)

另一个模糊的情况是,VLA在递归算法中可能有用 n, , 在哪里 n 足够小,您相信它不会溢出堆栈,但是在哪里可以做到 n 递归和个人级别的水平 n 元素。在C99之前,处理此案例的唯一方法无需服用 n^2 堆栈空间要使用 malloc. 。使用VLA,您可以在堆栈上完全解决问题。

请记住,这些VLA确实是有益的情况非常罕见。通常,VLA只是一种欺骗自己的方式,即记忆管理很容易,直到您被您创建的结果(琐碎到探索)漏洞咬伤。 :-)

编辑: 更好地解决OP的原始问题:

#define MAX_VLA 10000
int bar(size_t n)
{
    int arr[n <= MAX_VLA ? n : 1];
    if (sizeof arr/sizeof *arr < n) return ENOMEM;
    /* ... */
    return 0;
}

实际上,在各地的记忆条件下检查出来的昂贵。处理大量数据的企业方法是通过在单个早期检查点上定义大小的硬帽,并在盖帽命中时快速,优雅地失败。

我刚才建议的简单而愚蠢。但是,这是每种普通(非科学或特殊)产品总是可以做到的。以及客户通常的期望。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top