C语言链表结构中安全释放值的策略
Strategies for safely free-ing values in a linked-list structure in C
我使用 C 将大量数据存储在链表结构中。链表中的某些项目指向相同的 malloc 数据,这在释放链表结构时会导致问题。我可以通过复制插入链表结构的数据来解决这个问题,但这对我的程序有更大的影响。
也就是说:我 运行 关注这个问题的事实表明我有设计问题。因此,我正在寻找有助于解决此问题的策略和建议。
这里有一些代码突出了这个问题(是的,我知道我不应该像这样盲目地转换 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;
}
我看到很多关于 'safe' 版本的 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;
}
不过这个好像没什么效果。有什么建议吗?
这就是引用计数的用途。
每次分配东西时都使用这个结构:
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 );
}
}
关于这段代码。
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;
}
我使用 C 将大量数据存储在链表结构中。链表中的某些项目指向相同的 malloc 数据,这在释放链表结构时会导致问题。我可以通过复制插入链表结构的数据来解决这个问题,但这对我的程序有更大的影响。
也就是说:我 运行 关注这个问题的事实表明我有设计问题。因此,我正在寻找有助于解决此问题的策略和建议。
这里有一些代码突出了这个问题(是的,我知道我不应该像这样盲目地转换 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;
}
我看到很多关于 'safe' 版本的 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;
}
不过这个好像没什么效果。有什么建议吗?
这就是引用计数的用途。
每次分配东西时都使用这个结构:
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 );
}
}
关于这段代码。
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;
}