我们是否总是需要在 malloc/realloc 之后检查指针是否为空?
do we always need to check if the pointer not a null after malloc/realloc?
我现在正在学习C,在一些代码示例中我看到在我们为指针分配一些内存之后,我们必须检查指针是否不是NULL。例如:
CVector *vector = malloc(sizeof(struct CVectorImplementation));
assert(vector != NULL);
另一个例子:
vector->elements = realloc(vector->elements, vector->elemsz * vector->vec_capacity);
assert(vector->elements != NULL);
不过,我想既然指针已经被分配了,那么它的值就是分配内存的地址,所以它总是必要的吗?为什么?
如果您已重新分配原始指针以响应 realloc
,则为响应失败而做任何有用的事情都为时已晚。当realloc
失败时,它returnsNULL
,但它不会free
原始指针。因此,即使您对分配失败(不常见)有一些合理的响应,您也已经泄漏了您尝试 realloc
.
的内存
你主要问题的答案大多是"it's a bad idea to allow NULL
pointer dereferences to occur because it's a source of vulnerabilities";通常漏洞会出现在内核代码中(其中 NULL
与其他任何地方一样是有效地址),但即使它不可利用,也意味着程序会出现段错误,而不是以有用的方式报告错误。
realloc
函数尝试分配新内存。如果此分配失败,则 realloc
函数 returns NULL
。您的代码必须处理这种情况。
如果您想在这种情况下中止您的程序,那么您当前拥有的 assert
是合适的。如果你想恢复,那么你需要在评估情况时将 realloc
结果存储在一个单独的变量中,例如:
void *new = realloc(vector->elements, vector->elemsz * vector->vec_capacity);
if ( !new )
// take some action.... the old vector->elements is still valid
else
vector->elements = new;
分配失败通常会导致 2 个操作中的 1 个:
1) 退出带有诊断的程序。这比不检查并让代码继续到 who--knows--what 要好得多。
2) 在select情况下,代码可以应对失败。也许释放其他资源并重试,return 失败代码并将问题留给调用例程或编写 "suicide note" 并重新启动系统。 IAC,行动非常具体。
健壮的代码检查结果。初学者代码不会。
检查从 malloc/realloc 返回的指针是个好主意。
如果出现错误,您将返回一个空值。使用此检查对您有利,因为如果您稍后在程序中引用相同的指针并且您的程序突然崩溃,那么指针可能会设置为空。
如果您确实有一个来自 malloc/realloc 调用的有效指针,那么请确保在决定修改指针值之前和程序终止之前在 free()
函数中使用它,否则,你可能 运行 进入内存泄漏。
如果您需要更改指针值以写入您分配的内存的不同部分,请使用另一个指针。
这是 C 语言的代码,说明了我的意思:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char *block=calloc(1,10000);
if (block==NULL){
printf("Can't allocate memory\n");
return -1;
}
memset(block,48,20); //set 1st 20 bytes of memory to number zero (ascii code 48)
char *insideoftheblock=block+10; // I set a pointer to go to index #10 in the memory
*insideoftheblock='x';
*insideoftheblock++;
*insideoftheblock='y';
printf("Memory = '%s'",block);
free(block);
}
P.S.
我更新了我的代码以包含检查内存是否已实际分配的检查。
我现在正在学习C,在一些代码示例中我看到在我们为指针分配一些内存之后,我们必须检查指针是否不是NULL。例如:
CVector *vector = malloc(sizeof(struct CVectorImplementation));
assert(vector != NULL);
另一个例子:
vector->elements = realloc(vector->elements, vector->elemsz * vector->vec_capacity);
assert(vector->elements != NULL);
不过,我想既然指针已经被分配了,那么它的值就是分配内存的地址,所以它总是必要的吗?为什么?
如果您已重新分配原始指针以响应 realloc
,则为响应失败而做任何有用的事情都为时已晚。当realloc
失败时,它returnsNULL
,但它不会free
原始指针。因此,即使您对分配失败(不常见)有一些合理的响应,您也已经泄漏了您尝试 realloc
.
你主要问题的答案大多是"it's a bad idea to allow NULL
pointer dereferences to occur because it's a source of vulnerabilities";通常漏洞会出现在内核代码中(其中 NULL
与其他任何地方一样是有效地址),但即使它不可利用,也意味着程序会出现段错误,而不是以有用的方式报告错误。
realloc
函数尝试分配新内存。如果此分配失败,则 realloc
函数 returns NULL
。您的代码必须处理这种情况。
如果您想在这种情况下中止您的程序,那么您当前拥有的 assert
是合适的。如果你想恢复,那么你需要在评估情况时将 realloc
结果存储在一个单独的变量中,例如:
void *new = realloc(vector->elements, vector->elemsz * vector->vec_capacity);
if ( !new )
// take some action.... the old vector->elements is still valid
else
vector->elements = new;
分配失败通常会导致 2 个操作中的 1 个:
1) 退出带有诊断的程序。这比不检查并让代码继续到 who--knows--what 要好得多。
2) 在select情况下,代码可以应对失败。也许释放其他资源并重试,return 失败代码并将问题留给调用例程或编写 "suicide note" 并重新启动系统。 IAC,行动非常具体。
健壮的代码检查结果。初学者代码不会。
检查从 malloc/realloc 返回的指针是个好主意。 如果出现错误,您将返回一个空值。使用此检查对您有利,因为如果您稍后在程序中引用相同的指针并且您的程序突然崩溃,那么指针可能会设置为空。
如果您确实有一个来自 malloc/realloc 调用的有效指针,那么请确保在决定修改指针值之前和程序终止之前在 free()
函数中使用它,否则,你可能 运行 进入内存泄漏。
如果您需要更改指针值以写入您分配的内存的不同部分,请使用另一个指针。
这是 C 语言的代码,说明了我的意思:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(){
char *block=calloc(1,10000);
if (block==NULL){
printf("Can't allocate memory\n");
return -1;
}
memset(block,48,20); //set 1st 20 bytes of memory to number zero (ascii code 48)
char *insideoftheblock=block+10; // I set a pointer to go to index #10 in the memory
*insideoftheblock='x';
*insideoftheblock++;
*insideoftheblock='y';
printf("Memory = '%s'",block);
free(block);
}
P.S.
我更新了我的代码以包含检查内存是否已实际分配的检查。