c-函数内部的自由指针有点令人困惑



几周前,我了解了如何在函数内部分配和解除指针的正确方法,如示例linkedList:所示

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
}

所以在这个例子中,作者在通过值传递的指针上自由运行,所以在我看来这不应该起作用。但我研究了勘误表,并没有关于这个例子的注释。

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

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

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

我说得对吗?因为读了这个例子,我有一种感觉,我对这个话题的理解有问题。

我还去了Linux手册页,看到了免费的原型:

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

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

如果您正确地声明,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()的函数是可以的,在该函数中,只要函数的描述清楚地表明指针之后不能使用(无论指针的类型如何),就可以按值传递指针。但当然,您可以自由地用双指针定义函数,并将free()中的所有内容设置为NULL,就像这个非常简单的例子一样:

void myfree( void **pp )
{
   free( *p );
   *p = NULL;
}
...
int *p = malloc( sizeof *p );
...
myfree( &p );
// now p == NULL

您不需要使用:

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);

分配给CCD_ 6分配的CCD_。

使用

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);

但是其使用不必要的附加CCD_ 7和CCD_。

我会尽我所能在这里澄清。当您释放内存时,您应该释放已分配的实际内存。当您调用malloc这样的函数时,您需要给出想要malloc的数据大小。在您的情况下,"node"会像"malloc(sizeof(node))"一样进行malloc。

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

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

相关内容

  • 没有找到相关文章