2015-10-20 77 views
0

我正在学习C语言,在一些代码示例中,我看到在为指针分配一些内存之后,我们必须检查指针是否为NULL。例如:我们是否总是需要检查malloc/realloc之后指针是否为空?

CVector *vector = malloc(sizeof(struct CVectorImplementation)); 
assert(vector != NULL); 

另一个例子:

vector->elements = realloc(vector->elements, vector->elemsz * vector->vec_capacity); 
assert(vector->elements != NULL); 

不过,我觉得因为指针已经分配,​​那么它有分配的内存作为其值的地址,因而它总是需要?为什么?

+1

这样做是为了检查内存分配是否成功。 – SKD

+0

sidenote:assert不是检查内存分配是否成功的好方法,assert只在调试时才有效。你应该做一个if语句,这样它就可以在调试和发布模式下工作。 –

回答

1

检查从malloc/realloc返回的指针是个好主意。 如果出现错误,您将返回空值。使用这个检查是有好处的,因为如果你在程序的后面引用同一个指针,并且你的程序突然崩溃,那么指针可能被设置为null。

如果你确实有一个来自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); 
} 

附:

我更新了我的代码,包含一个检查内存是否已被实际分配。

2

如果您已重新分配原始指针以响应realloc,那么为响应故障做任何有用的事情为时已晚。当realloc失败时,它返回NULL,但是它不是free原指针。所以即使你对分配失败(不常见)有一些合理的回应,你已经泄露了你试图使用的内存realloc

您的主要问题的答案大多是“允许NULL指针取消引用发生是一个坏主意,因为它是一个漏洞的来源”;通常在内核代码中会出现漏洞(其中NULL与其他任何地址一样有效),但即使它不可被利用,也意味着程序段错误,而不是以有用的方式报告错误。

1

realloc函数试图分配新的内存。如果此分配失败,则realloc函数返回NULL。你的代码必须处理这种情况。

如果你想在这种情况下放弃你的程序,那么你目前使用的assert是合适的。如果要恢复,那么你将需要realloc结果存储在一个单独的变量,而你审时度势,如:

1:

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; 
+0

'新'是一个可怕的名字使用:-) –

+0

@Cyber​​Spock我认为这是一个好名字,它会淘汰使用不同语言的编译器编译他们的C代码的人! –

+0

是的,可能是但它也是一个非描述性的名字......“新”是什么? (从来不是,不重要) –

0

一个2合1的动作分配失败的典型结果)用诊断程序退出程序。这比不检查并让代码继续向谁知道 - 什么更好。

2)在某些情况下,代码可以应付失败。也许可以释放其他资源并再次尝试,返回失败代码并将问题留给调用例程或撰写“遗书”并重新启动系统。 IAC,行动是非常具体的情况。

鲁棒的代码检查结果。初学者代码不。