我为可能的重复道歉(无法找到答案):
我们是否需要确保可变长度数组的分配已成功完成?
例如:
void func(int size)
{
int arr[size];
if (arr == NULL)
{
// Exit with a failure
}
else
{
// Continue as planned
}
}
很明显,答案是是,但语法arr == NULL
感觉有点不寻常。
由于
更新
我承认我没有确定上面的代码甚至编译(假设确实如此)。
如果它没有编译,则意味着无法断言可变长度数组的分配。
因此,我认为如果分配失败,程序会立即崩溃。
这将是一个非常尴尬的案例,因为在非法内存访问(读取或写入)之后程序崩溃是有意义的,但在非成功的内存分配之后却没有。
或许这个分配不会引起任何影响,但是一旦我在一个条目中访问该阵列,那么#34;#34;在堆栈外,我可能会遇到内存访问冲突(如堆栈溢出)......?
老实说,如果更多的局部变量跟随它们(特别是其他的VLA),我甚至无法看到如何在堆栈上分配VLA,所以我也希望能够回答这个问题。
答案 0 :(得分:2)
这个问题来自一个略有缺陷的第一个前提。您无法检查数组是否为NULL
,因为这是一个热门的讨论主题an array is not a pointer in C。数组 存储对象,就地。
如果没有分配数组,则无法访问可访问数组名称的代码。本地数组与任何其他本地变量完全相同:它的存在是固有的,并假设周围的代码完全运行,并且语言中没有概念用于检查是否已经“分配”了任何给定的变量槽。 (正如问题说明中的评论,“堆栈”是C级操作的概念 - 语言假定它“发生”,由未指定的魔法)。为了使代码在最基本的层面上有意义,它必须假设这一点总是成功。
在无法分配数组的情况下发生的情况与运行时无法为任何其他局部变量分配空间时发生的情况相同 - 情况固有未定义且不可确定的,因为违反了C语言抽象机器的假设。该语言没有(完全正式的)概念甚至可以表达这一点,更不用说检查它或从中恢复,因此测试它同样超出了范围。就像堆栈溢出一样,这基本上可以保证导致致命的崩溃。
由于以下几个原因,这不使VLA无用,
VLA的许多用途都不会危及生命。也许变种的唯一用途是选择3到5之间的数字?对于空间而言,这并不比使用更多的标量本地人更糟糕。
正如避免无限递归一样,程序员需要证明C编译器没有的某些属性,类似地,你应该设计你的程序,至少在空间量上有一个弱的界限,可以在任何给定的时间。例如,你可以向自己证明没有VLA函数是递归的,或者是从递归函数中调用的,并且没有一个函数使用超过例如 10K的空间 - 这非常有用并且应该是安全的。 / p>
您可以将VLA视为优化,以便您可以节省空间,否则您必须分配一个静态大小的本地数组(例如,在第一个示例中,始终分配5而不是3)。只要您知道并设计静态上限,它们就可以有效地保证您的程序更安全免于溢出,提供一个选项,当它不是时,并不总是使用尽可能多的空间必需的。