是否需要检查没有 malloc() 声明的 C 数组的有效性?
Do C arrays declared without malloc() need to be checked for validity?
(如果有人有建议,我会改写标题,我知道这有点尴尬。)
在使用 malloc()
为 C 中的动态数组分配内存时,我知道通过验证指针不为 NULL 来检查调用是否成功。是否需要对 C 中显式声明的数组执行相同的检查,例如在以下示例中(取自 this question)?
char arrinit[5];
char (*arrinit_two)[5] = &arrinit;
简而言之:没有!
编译器将确保您的数组有足够的静态定义内存。
通常(取决于您声明它们的方式),它们将分配在堆栈上,当堆栈上没有足够的剩余内存时,您的程序可能会在您进行任何检查之前崩溃,或者您将无法采取任何补救措施。
顺便说一句:无论如何,你也不会得到 NULL 值,因为系统会给你一些地址值,即使没有剩余内存(或者它之前已经崩溃)。
当然有一种情况,你应该小心:当你想分配非常大的内存(一个大数组)时,你应该这样做分配。在许多系统上,进程的堆栈大小受到限制,因此当您在堆栈上分配大量内存(编译器为您完成)时比使用 malloc 时(因为有不是相同的限制)。
当然,在今天的计算机上,这意味着,在它产生任何影响之前,您可以拥有至少一些 MB 的数组。对于小于 1MB 的数组,您无需费心。
不,如果指针指向堆栈变量则不需要检查,我想你的意思是
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;
那么编译器将无法警告你,但条件仍然不能为假,因为数组是在创建函数堆栈帧时分配的,所以如果不能分配数组,那么它将是无法调用函数。
如果你定义一个数组对象,检查它是否分配成功是不必要的或不可能的。
如果用 static storage duration 定义(即在任何函数体外部定义或用 static
关键字定义),则所需内存量为在编译时确定,并在加载程序时分配。如果没有足够的空间,根据系统的不同,您的程序很可能无法执行。
如果它是在没有 static
关键字的函数中定义的,那么内存将在调用该函数时或在包含它的块的入口处分配。如果 that 分配失败,则行为未定义。最常见的是,该程序将死于 "stack overflow" 或类似的东西。该语言没有提供一种方法来提前检测这样的分配是否会成功,或者在它失败之后检测。
这意味着像这样的东西:
{
char arr[5];
if (arr != NULL) ...
}
几乎肯定不会检测到任何分配失败;已声明对象的地址始终为非空。
(如果有人有建议,我会改写标题,我知道这有点尴尬。)
在使用 malloc()
为 C 中的动态数组分配内存时,我知道通过验证指针不为 NULL 来检查调用是否成功。是否需要对 C 中显式声明的数组执行相同的检查,例如在以下示例中(取自 this question)?
char arrinit[5];
char (*arrinit_two)[5] = &arrinit;
简而言之:没有!
编译器将确保您的数组有足够的静态定义内存。
通常(取决于您声明它们的方式),它们将分配在堆栈上,当堆栈上没有足够的剩余内存时,您的程序可能会在您进行任何检查之前崩溃,或者您将无法采取任何补救措施。
顺便说一句:无论如何,你也不会得到 NULL 值,因为系统会给你一些地址值,即使没有剩余内存(或者它之前已经崩溃)。
当然有一种情况,你应该小心:当你想分配非常大的内存(一个大数组)时,你应该这样做分配。在许多系统上,进程的堆栈大小受到限制,因此当您在堆栈上分配大量内存(编译器为您完成)时比使用 malloc 时(因为有不是相同的限制)。
当然,在今天的计算机上,这意味着,在它产生任何影响之前,您可以拥有至少一些 MB 的数组。对于小于 1MB 的数组,您无需费心。
不,如果指针指向堆栈变量则不需要检查,我想你的意思是
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;
那么编译器将无法警告你,但条件仍然不能为假,因为数组是在创建函数堆栈帧时分配的,所以如果不能分配数组,那么它将是无法调用函数。
如果你定义一个数组对象,检查它是否分配成功是不必要的或不可能的。
如果用 static storage duration 定义(即在任何函数体外部定义或用 static
关键字定义),则所需内存量为在编译时确定,并在加载程序时分配。如果没有足够的空间,根据系统的不同,您的程序很可能无法执行。
如果它是在没有 static
关键字的函数中定义的,那么内存将在调用该函数时或在包含它的块的入口处分配。如果 that 分配失败,则行为未定义。最常见的是,该程序将死于 "stack overflow" 或类似的东西。该语言没有提供一种方法来提前检测这样的分配是否会成功,或者在它失败之后检测。
这意味着像这样的东西:
{
char arr[5];
if (arr != NULL) ...
}
几乎肯定不会检测到任何分配失败;已声明对象的地址始终为非空。