C中的链接列表(内存问题)

时间:2010-09-04 22:43:55

标签: c list memory linked-list

我在C中创建一个简单的链表,以便习惯一些内存管理。我已经定义了一个节点结构,它包含一个char *键,一个char *值和一个节点* next。

void newnode(node *n, int x, int y)
{
    n->key = malloc(x*sizeof(char));
    n->value = malloc(y*sizeof(char)); 
}

//This how i create a new node given a key and value to make sure that I have allocated the proper amount of space. x and y are the strlengths of the key and value being added.

// In the add function I use the following two lines (when it is valid to add a new key value pair)

current->next = malloc(sizeof(node));
node_newnode(current->next,strlen(key),strlen(value));

// My remove function then searches for a key and if that key exists in the structure it removes that node. I use a delete point to keep track of the node needing deletion.

void remove(dict *d, const char *key)
{
    node* delete;
    node* current;
    current = d->head;

    while(current->next != NULL){

        if(strcmp(current->next->key,key)==0){
            delete = current->next;
            if(current->next->next != NULL)
                current = current->next->next;
            else
                current->next = NULL;
            node_destroy(delete);
            break;
        }

        current = current->next;
    }
}

// Here is the node_destroy function I used in remove. 

void node_destroy(node* delete)
{ 
    free(delete->key); 
    free(delete->value); 
    free(delete); 
} 

我遇到了这个删除功能的问题。从本质上讲,它似乎没有正确删除键值节点,而是留下节点的残余而不是完全删除它。我不知道为什么这是可能的,特别是当我设置指针指向需要删除的节点时。在最坏的情况下,我觉得我应该只是泄漏内存,但不知何故这些节点没有被删除,并且当我打印出字典时仍然是结构的一部分。我不得不关注内存的布局,我真的不知道什么是错的。

有什么建议吗?

P.S。我的节点销毁功能是否没有正确释放内存?

5 个答案:

答案 0 :(得分:3)

可以立即说的是,如果您的键和值是字符串(并且它们是根据您的代码),那么要在内存中存储长度为N的字符串,您需要分配N + 1个字节,而不是N字节。零终结符字符需要额外的字节。在您的代码中,您将相应字符串的strlen作为xy参数传递给分配函数,然后为xy字符准确分配关键和价值。这已经错了。

您没有显示如何填写分配的键和值内存(可能是strcpy),但它肯定会将分配的内存一直超出1个字节而带来灾难性的后果。

在C语言中,可以通过malloc()calloc()函数获取内存。 有关详细信息,请访问http://scanftree.com/Data_Structure/linked-list

答案 1 :(得分:1)

您永远不会从链接列表中删除已删除的节点。它应该是(检查边缘情况):

current->next = current->next->next;

E.g。如果你有:

{foo:bar} => {bar:baz} => {咕:盖}

你要删除{bar:baz},你需要设置foo的下一个指针指向goo。除非删除current->next成为最后一个元素,否则您不会设置current

因此,释放的内存仍然存在于列表中,您稍后会阅读它。这是未定义的行为,但正如您所看到的,内存可能无法立即重用。

答案 2 :(得分:0)

首先,你没有在字符串末尾为空值分配空间......

另一个可能的问题是,您应该确保初始化n->next = NULL;

最后,

current = current->next->next;

应该是

current->next = ...

答案 3 :(得分:0)

current->next = malloc(sizeof(node));

应该是     current-> next = calloc(1,sizeof(node)); / *因为安全NULL测试 - >下一个! * /

void newnode(node *n, int x, int y)
{
    n->key = malloc(x*sizeof(char));
    n->value = malloc(y*sizeof(char)); 
}

应该是

void newnode(node *n, int x, int y)
{
    n->key = malloc(x+1); /* because x comes from strlen() and sizeof(char)==1 */
    n->value = malloc(y+1); /* because x comes from strlen() and sizeof(char)==1 */ 
}

答案 4 :(得分:-3)

  

current-> next = malloc(sizeof(node));

我假设你的意思是sizeof(node *)?另外,我可以看到用于定义节点的结构吗?或许整个计划?