关于函数内部的自由指针有点混乱

时间:2015-03-23 19:00:29

标签: c pointers malloc free

几个星期前,我学习了如何在函数内部分配和处理指针的正确方法,所以在示例中给出了链接:

typedef struct _node {
    void *data;
    struct _node *next;
} Node;

typedef struct _linkedList {
    Node *head;
    Node *tail;
    Node *current;
} LinkedList;

在我看来,破坏队列的正确方法是使用获取指向我想要删除的节点的指针的函数:

void destroy (Node ** node) 

或更实际的示例指针指向指向要删除的列表的指针和指针。

void destroy (LinkedList * list, Node ** node) 

但现在我正在阅读“理解C指针”这本书并遇到问题,因为在第6章指向结构的指针中有一个函数destroyList的例子:

void delete(LinkedList *list, Node *node) {
    if (node == list->head) {
        if (list->head->next == NULL) {
            list->head = list->tail = NULL;
        } else {
            list->head = list->head->next;
        }
    } else {
        Node *tmp = list->head;
        while (tmp != NULL && tmp->next != node) {
            tmp = tmp->next;
        }
       if (tmp != NULL) {
            tmp->next = node->next;
        }    
    }   
    free(node);  //free on pointer copy value not pointer
}

所以在这个例子中,作者在按值传递的指针上运行free,所以在我看来这应该不起作用。但我查看了勘误表,并没有关于这个例子的说明。

在这种情况下,我理解List是使用正确的list实例的函数参数,但应该是:

free(list->head) ; //It should work?

然后还为分配的List释放内存。

我是对的吗?因为阅读这个例子,我觉得我对这个话题有很好的理解。

我也去了Linux Man Page,我看到了免费原型:

 void free(void *ptr);    // http://linux.die.net/man/3/free

那么为什么每个人都告诉当你想要释放内存时将指针传递给指针但是在标准库中相同的自由函数作为参数而不是指针指针而是指针,它是如何正常工作的?

3 个答案:

答案 0 :(得分:1)

正确地说,free( void *p )释放了内存p点,但是当地址按值传递时,它将对调用者保持不变。因此你可能遇到这样的问题:

int *p = malloc( sizeof *p );

*p = 1;
free( p );
...

if( p )
   *p = 2;     // Undefined Behaviour!!! although p is free()'d it's still != NULL

所以你经常会找到

free( p );
p = NULL;

尽管如此,在我看来,只要函数的描述清楚地表明指针一定不能,你可以编写free()之类的函数来传递指针值。 之后使用(无论是什么类型的指针)。但是你当然可以自由地用双指针定义函数并将你所有的东西设置为NULL里面的void myfree( void **pp ) { free( *p ); *p = NULL; } ... int *p = malloc( sizeof *p ); ... myfree( &p ); // now p == NULL ,就像这个非常简单的例子一样:

{{1}}

答案 1 :(得分:0)

您无需使用:

void destroy (LinkedList * list, Node ** node) 

使用

void destroy (LinkedList * list, Node * node) 

就足够了。

您可以使用:

void destroy(int* pointer)
{
   free(pointer);
}

int* ip = malloc(sizeof(int));
destroy(ip);

到由free和相关函数分配的malloc内存。

使用

void destroy(int** pointer)
{
   free(pointer);
}

int* ip = malloc(sizeof(int));
destroy(&ip);

错了。

您可以使用:

void destroy(int** pointer)
{
   free(*pointer);
}

int* ip = malloc(sizeof(int));
destroy(&ip);

但是使用了不必要的其他&*

答案 2 :(得分:0)

我会尽力在这里澄清一下。当你释放内存时,你应该释放分配的实际内存。当你调用像malloc这样的函数时,你应该给出你想要malloc的数据大小。在你的情况下,'node'将被像malloc(sizeof(node))'一样被malloced。

同样,当您调用free时,您打算释放已分配的整个内存块。如果你要释放指向内存的指针,你实际上并没有释放内存,而是释放指向它的东西。现在你已经泄露了内存,因为没有任何东西可以再访问malloced节点了。

所以在你引用的代码中,他没有释放节点的值,他正在释放分配给节点的内存。当他调用free(node)时,他正在传递一个指向节点的指针(因为一个节点指针被传递给该函数),然后free释放该节点的内存。