【问题标题】:Do C arrays declared without malloc() need to be checked for validity?是否需要检查没有 malloc() 声明的 C 数组的有效性?
【发布时间】:2015-02-23 02:37:15
【问题描述】:
(如果有人有建议,我会改写标题,我知道这有点尴尬。)
在 C 中使用 malloc() 为动态数组分配内存时,我知道通过验证指针不为 NULL 来检查调用是否成功。是否需要对 C 中显式声明的数组执行相同的检查,例如以下示例(取自 this question)?
char arrinit[5];
char (*arrinit_two)[5] = &arrinit;
【问题讨论】:
标签:
c
arrays
pointers
memory
【解决方案1】:
简而言之:不!
编译器将确保您的数组有足够的内存供您静态定义。
通常(取决于您如何声明它们),它们将被分配到堆栈上,当您在堆栈上没有足够的内存时,您的程序可能会在您进行任何检查之前崩溃,或者您不会能够采取任何补救措施。
顺便说一句:无论如何,你也不会得到一个 NULL 值,因为系统会给你一些地址值,即使没有留下任何内存(或者它之前已经崩溃了)。
当然有一种情况,你应该小心:当你想分配大量的内存(一个大数组)时,你应该用 malloc 来做。在许多系统上,进程的堆栈大小是有限的,因此当您在堆栈上分配大量内存时(编译器为您分配)比使用 malloc 分配大量内存时(因为那里不是相同的限制)。
当然,在今天的计算机上,这意味着您可以拥有至少一些 MB 的数组,然后才会产生任何影响。对于小于 1MB 的数组,您无需费心。
【解决方案2】:
如果你定义了一个数组对象,那么检查它是否分配成功要么是不必要的,要么是不可能的。
如果使用静态存储持续时间定义(即,在任何函数体之外定义或使用static 关键字定义),则所需的内存量在编译时确定并分配当你的程序被加载时。如果没有足够的空间,取决于系统,您的程序很可能无法执行。
如果它是在没有static 关键字的函数内定义的,则在调用该函数或进入包含它的块时分配内存。如果 那个 分配失败,则行为未定义。最常见的程序会因“堆栈溢出”或类似情况而死。该语言没有提供一种方法来提前检测这种分配是否会成功,或者在它失败后检测。
意思是这样的:
{
char arr[5];
if (arr != NULL) ...
}
几乎可以肯定永远不会检测到任何分配失败;声明对象的地址总是非空的。
【解决方案3】:
不,如果指针指向堆栈变量,则不需要检查,我猜你的意思是
int array[5] = {1, 2, 3, 4, 5};
int *pointer;
pointer = array;
if (pointer != NULL) /* will always be true */
...
有编译器警告会发出警告
if (array != NULL)
并告诉你这个条件总是正确的。
如果你声明一个指针并指向它,比如
int *pointer = array;
那么编译器将无法警告您,但条件仍然不能为假,因为数组是在创建函数堆栈帧时分配的,因此如果无法分配数组,则无法分配调用函数。