简体   繁体   English

安全释放C中链表结构中的值的策略

[英]Strategies for safely free-ing values in a linked-list structure in C

Using C I'm storing a large amount of data in a linked list structure. 使用C,我将大量数据存储在链表结构中。 Some items in the linked list point to the same malloc'd data and this is causing issues when it comes to free-ing the linked list structure. 链表中的某些项指向相同的已分配数据,这在释放链表结构时引起问题。 I could solve the issue by copying the data as it's inserted into the linked list structure, but this has bigger implications for my program. 我可以通过复制插入链表结构中的数据来解决该问题,但这对我的程序有更大的影响。

That said: the fact that I'm running into this issue suggests I have a design problem. 就是说:我遇到这个问题的事实表明我有一个设计问题。 As such, I'm looking for strategies and suggestions to help deal with this problem. 因此,我正在寻找有助于解决此问题的策略和建议。

Here's some code that highlights the issue (and yes, I know that I shouldn't be blindly casting malloc like this): 这是一些突出问题的代码(是的,我知道我不应该像这样盲目地投射malloc ):

char *val = (char *)malloc(256);
strcpy(val, "Dummy value");

LinkedListItem *itemB = (LinkedListItem *)malloc(sizeof(LinkedListItem));
itemB->value = val;
itemB->next = NULL;

LinkedListItem *itemA = (LinkedListItem *)malloc(sizeof(LinkedListItem));
itemA->value = val;
itemA->next = itemB;

LinkedListItem *cur = itemA;
while(cur)
{
    free(cur->value); // the crash will occur here, when performing a double free on itemB's value pointer
    cur->value = NULL;

    cur = cur->next;
}

I've seen many references to a 'safe' version of free that essentially NULL's the pointer after free-ing it, like so: 我已经看到许多关于free的“安全”版本的引用,在释放它之后,指针实际上是NULL,就像这样:

void free_generic(void **pp)
{
    assert(pp);

    if(pp != NULL)
    {
        free(*pp);
        *pp = NULL;
    }
}

while(cur)
{
    free_generic(&cur->value);
    cur = cur->next;
}

But this seems to have no effect. 但这似乎没有效果。 Any suggestions? 有什么建议么?

This is what reference-counting is for. 这就是引用计数的目的。

Use this struct every time you allocate something: 每次分配一些东西时都使用此结构:

struct AllocatedStringValue {
    char* string;
    size_t refCount;
};


struct AllocatedStringValue value;
value.refCount = 0;
value.string = calloc( 256, sizeof(char) );

LinkedListItem *itemB = (LinkedListItem *)malloc(sizeof(LinkedListItem));
itemB->value = value;
itemB->next = NULL;
value.refCount++;

...

itemA->value = value;
value.refCount++;

...

while(cur) {
    if( cur->value.refCount > 0 ) {
        cur->value.refCount--;
    } else {
        free( cur->value->string );
    }
}

regarding this code snippit. 关于此代码段。

void free_generic(void **pp)
{
    assert(pp);       // this and following 'if' are testing same thing
                      // and this assert() should never fail as
                      // 'pp' is the address of a variable

    if(pp != NULL)    // could only fail if variable located at address 0
                      // should be: 'if( *pp )'
    {
        free(*pp);
        *pp = NULL;
    }
}

while(cur)
{
    free_generic(&cur->value);
    cur = cur->next;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM