C/C++ free(NULL)的思考

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/diangangqin/article/details/100160170

最近code review的时候发现了一段magic code,free的指针指向了NULL,当时胆战心惊,第一反应就是free一个空指针会引起NE,应该和double free一个地址是同样的效果。但是冷静下来,想到这段代码是一段老code了,而且还在一直运行,应该没有问题才对,不然的话早就暴露出来了。

查到C标准库free有下面的描述。

**Description
The C library function void free(void ptr) deallocates the memory previously allocated by a call to calloc, malloc, or realloc.
Declaration
Following is the declaration for free() function.
void free(void ptr)
Parameters
ptr —— This is the pointer to a memory block previously allocated with malloc, calloc or realloc to be deallocated. If a null pointer is passed as argument, no action occurs.
Return Value
This function does not return any value.

如果free一个空指针,是没有任何事情发生的。和double free一个指针是不一样的。所以在申明一个指针的时候,最好赋初值NULL,例如char* str = NULL,后面不小心free了也没有问题发生。free一块malloc的指针后,需要将指针置为NULL,可以避免double free。原先以为free一块malloc的指针后将指针置为NULL是编码规则要求的,但是现在看是有着实际意义的。
现在维护的code中含有大量的下面类似的code。其实这种写法也不能避免double free,因为free之后没有将指针置为NULL。

if (pointer != NULL) {
    free(pointer);
}

下面写法会更好

if (pointer != NULL) {
    free(pointer);
    pointer = NULL;
}

但是每次free之前还是都要判断pointer是否为NULL,感觉也不是很好,如果大家都养成free之后将pointer置为NULL并且声明定义指针赋初值NULL的习惯,那么判断条件是可以remove掉的。

{
    free(pointer);
    pointer = NULL;
}

下面写一个sample供大家参考。

typedef struct {
    int id;
    cahr* str;
} TestParam;

void testFree(int id) {
    TestParam *testParam = NULL;
    testParam = (TestParam*)malloc(sizeof(TestParam));
    if (testParam == NULL) {
        return;
    }
    memeset(testParam, 0, sizeof(TestParam));
    testParam->id = id;
    testParam->str = NULL;
    // testParam->str 可能会在函数中某些地方通过malloc的方式赋值,也可能不会。
    // 无论testParam->str是否通过malloc赋过值,都可以直接使用free函数,因为testParam->str初始值为NULL。当然条件是前面没有出现过free之后没有赋NULL的逻辑。
    free(testParam->str);
    testParam->str = NULL;
    free(testParam);
    testParam = NULL;
}

因为一个项目不会是一个人开发,知识准备可能不一样,我们只能严格要求自己了。free的时候需要判断是否是NULL,free之后置NULL。申明指针时初始值设为NULL。
所以最后一段code,一般会写成:

if(testParam != NULL) {
    if (testParam->str != NULL) {
        free(testParam->str);
        testParam->str = NULL;
    }
    free(testParam);
    testParam = NULL;
}

另外free的指针只限于malloc, calloc or realloc这三个分配后的内存指针。如果自己定义了一个局部指针
char str[] = “abcdef”;
如果free(str),我推测应该什么都不会做才对(undefined behavior occurs),和free(NULL)一样,大家可以做一下试验,毕竟结构和malloc的结构不一样,当然也要避免这种情况的发生。
free一块malloc的内存后,这块内存就是未知的,可能保持原来的值,也可能已经被分配了,这时候再次free就会导致严重问题了(undefined behavior occurs)。

编程真是学无止境,只能靠一点一点积累和保持一颗好奇和学习的心了。越是认为简单的东西,包含的知识越是丰富。

猜你喜欢

转载自blog.csdn.net/diangangqin/article/details/100160170
今日推荐