【问题标题】:Freeing char* data not working释放 char* 数据不起作用
【发布时间】:2018-09-16 16:10:37
【问题描述】:

我有一个列表,列表中的每个节点都包含一个 char *data 字段,该字段必须与节点本身进行 malloc'd,但是当我尝试释放该数据时,控制台会停止,它不会崩溃,他们没有错误,什么都没有。但是,如果我将其注释掉并仅释放列表节点,它就可以正常工作。

我这样做对吗?

void removeSpecificData(List *list, char *course)
{
    ListNodePtr currentNode = list->head;
    ListNodePtr previousNode = NULL;

    while (currentNode != NULL)
    {
        if (strcmp(currentNode->data, course) == 0)
        {
            ListNodePtr nodeToFree = currentNode;

            if (previousNode == NULL)
            {
                list->head = currentNode->nextNode;
                currentNode = list->head;
            }
            else
            {
                previousNode->nextNode = currentNode->nextNode;
                currentNode = previousNode->nextNode;
            }

            printf("Free Data");
            free(nodeToFree->data);
            printf("Free Node");
            free(nodeToFree);
        }
        else
        {
            previousNode = currentNode;
            currentNode = currentNode->nextNode;
        }
    }
}

这是我的 createListNode 函数,以防需要查看。

ListNodePtr createListNode(char *newCourse)
{
    ListNodePtr newNode = (ListNodePtr)malloc(sizeof(struct ListNode));
    newNode->data = (char *)malloc(sizeof(strlen(newCourse) + 1));
    strcpy(newNode->data, newCourse);
    newNode->nextNode = NULL;

    return newNode;
}

提前致谢。

【问题讨论】:

  • 第一个函数不能编译,因为变量 nodeToFree 既没有声明也没有赋值。所以这条语句 free(nodeToFree);没有意义。:)

标签: c pointers char malloc free


【解决方案1】:

以下行不正确。

newNode->data = (char *)malloc(sizeof(strlen(newCourse) + 1));

sizeof() 部分不正确。如果字符串的长度大于sizeof(size_t),您最终分配的内存将少于您的需要。在它之后对strcpy 的调用将使用超出您分配的内存。因此,您的程序将具有未定义的行为。

使用

newNode->data = malloc(strlen(newCourse) + 1);

Do I cast the result of malloc?

【讨论】:

    【解决方案2】:

    分配大小不正确。只有在尝试释放内存(损坏的内存列表)时,系统才会检测到它。

    为什么不只是:

    newNode->data = strdup(newCourse);
    

    它将分配适当的大小(与您的尝试不同)并同时复制字符串(不需要mallocstrcpy

    【讨论】:

    • "Why not" --> 高可移植性排除了使用strdup()malloc()strcpy() 都在标准 C 库中。 strdup() 不是。然而,strdup() 非常普遍 - 无处不在。
    【解决方案3】:

    对于初学者来说,函数removeSpecificData 至少有一个错字或错误,因为没有变量nodeToFree 的声明,并且没有为变量分配任何值。

    所以这个说法

    free(nodeToFree);
    

    没有意义。

    同样在这个 else 块中,第二个表达式语句没有意义。

        else
        {
            previousNode->nextNode = currentNode->nextNode;
            currentNode = previousNode->nextNode;
            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
        }
    

    函数太复杂了。它可以写得更简单。例如

    void removeSpecificData(List *list, const char *course)
    {
        ListNodePtr *currentNode = &list->head;
    
        while ( *currentNode != NULL && strcmp( ( *currentNode )->data, course) != 0 )
        {
            currentNode = &( *currentNode )->nextNode;
        }
    
        if ( *currentNode != NULL )
        {
            ListNodePtr tmp = *currentNode;
            *currentNode = ( *currentNode )->nextNode;
    
            free( tmp->data );
            free( tmp );
        }
    }    
    

    至于函数createListNode然后是表达式

    strlen(newCourse) + 1
    

    类型为size_t。所以顺便说一下不计算表达式的值:)

    sizeof(strlen(newCourse) + 1)
    

    等价于表达式

    sizeof( size_t )
    

    根据size_t类型的定义,等于4或8。

    你只需要写

    newNode->data = (char *)malloc( strlen(newCourse) + 1 );
    

    【讨论】:

    • nodeToFree 被声明为最接近它的第一次使用,在找到课程时的 if 语句中,对 mallocing 的更改解决了这个问题,谢谢。 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-21
    相关资源
    最近更新 更多