我有以下功能:
/* undef: from s from hashtab */
void undef(char *s) {
struct nlist *currentPtr, *previousPtr;
for (previousPtr = NULL, currentPtr = hashtab[hash(s)];
currentPtr != NULL;
previousPtr = currentPtr, currentPtr = currentPtr->next) {
if (strcmp(currentPtr->name, s) == 0) {
if (previousPtr == NULL) /* first element */
hashtab[hash(s)] = currentPtr->next;
else /* element in the middle or at the end */
previousPtr->next = currentPtr->next;
/* free memory */
free(currentPtr->name);
free(currentPtr->defn);
//free(currentPtr);
}
}
}
currentPtr
指向由malloc
分配的内存。
currentPtr->name
和currentPtr->defn
指向通过strdup
复制的字符数组。
我不确定释放列表项的内存的正确方法是什么。
如果我使用
free(currentPtr->name);
free(currentPtr->defn);
然后我没有分段错误,但我相信字符数组内存被释放,但列表结构元素本身不是。
如果我使用
free(currentPtr);
然后我也没有分段错误,但我相信我释放了列表结构元素本身,而不是字符数组内存。
使用
free(currentPtr->name);
free(currentPtr->defn);
free(currentPtr);
给我分段错误。但我认为这是正确的做法。
哪个是正确的?为什么会失败?
答案 0 :(得分:4)
您需要稍微改变一下策略,因为currentPtr
是调用
free(currentPtr);
这是我的建议:
for (previousPtr = NULL, currentPtr = hashtab[hash(s)];
currentPtr != NULL;
previousPtr = currentPtr) {
if (strcmp(currentPtr->name, s) == 0)
{
if (previousPtr == NULL) /* first element */
hashtab[hash(s)] = currentPtr->next;
else /* element in the middle or at the end */
previousPtr->next = currentPtr->next;
/* free memory */
free(currentPtr->name);
free(currentPtr->defn);
// Get hold of the next pointer before free'ing currentPtr
struct nlist *tempPtr = currentPtr->next;
free(currentPtr);
currentPtr = tempPtr;
}
else
{
currentPtr = currentPtr->next;
}
}
更新,更精简的版本
由于您在四个地方使用currentPtr->next
,因此可以使用以下方法简化循环:
struct nlist *nextPtr = NULL;
for (previousPtr = NULL, currentPtr = hashtab[hash(s)];
currentPtr != NULL;
previousPtr = currentPtr, currentPtr = nextPtr) {
nextPtr = currentPtr->next;
if (strcmp(currentPtr->name, s) == 0)
{
if (previousPtr == NULL) /* first element */
hashtab[hash(s)] = nextPtr;
else /* element in the middle or at the end */
previousPtr->next = nextPtr;
/* free memory */
free(currentPtr->name);
free(currentPtr->defn);
free(currentPtr);
}
}