【问题标题】:C - how to get rid of memory leaks?C - 如何摆脱内存泄漏?
【发布时间】:2020-09-18 18:51:25
【问题描述】:

我怎样才能摆脱例如这个函数的内存泄漏:

void AddData(Data **head, char *sentence, int number) {
    Words *words = NULL;
    char delimiters[] = " \n\0";
    char *token = strtok(sentence, delimiters);
    while (token != NULL) {
        if (IsAlphabetical(token) == 1) {
            char *string = (char *)malloc((strlen(token) + 1) * sizeof(char));
            strcpy(string, token);
            AddWords(&words, string);
            free(string);
        }
        token = strtok(NULL, delimiters);
    }

    Data *temp = *head;
    Data *newData = (Data *)malloc(sizeof(Data));

    newData->lineNumber = number;
    newData->words = words;
    newData->pNext = NULL;

    if (*head == NULL)
        *head = newData;
    else {
        while (temp->pNext != NULL)
            temp = temp->pNext;

        temp->pNext = newData;
    }
}

我个人的看法是由于newDatatempwords 变量而出现泄漏。

我有一些类似的功能会导致同样的问题。 我也有删除数据结构的功能,但是当我在前一个函数的末尾以这种方式调用它时,DeleteData(&temp) 程序将不会执行。我想是因为我的整个列表都被删除了。

void DeleteData(Data **head) {
    Data *temp = *head;
    while (temp->pNext != NULL) {
        Data *next = temp->pNext;
        DeleteWords(&temp->words);
        free(temp);
        temp = next;
    }
    free(temp); /* to check that */
    *head = NULL;
}

我该如何解决这个问题?

【问题讨论】:

  • 不存在的例程AddWords() 是否分配了任何东西,如果是,这些分配器是否被释放?最初分配给newData 的分配器是否被释放?
  • 编辑问题以提供minimal reproducible example,包括输入数据、观察到的程序行为、所需行为以及您掌握的存在泄漏的证据。
  • 你没有为temp 分配任何东西,所以不会有任何泄漏。你是否通过 valgrind 或其他类似的工具运行代码来告诉你是否存在泄漏?但是由于这只是部分代码,所以不可能全部都说出来
  • 发布我的所有代码是个好主意吗?大约600行
  • 我使用 drmemeory 运行

标签: c memory-leaks dynamic-memory-allocation free singly-linked-list


【解决方案1】:

以下是我发现的一些问题:

  • char delimiters[] = " \n\0"; 中的尾随 \0 没有用。

  • 测试if (IsAlphabetical(token) == 1) 可能过于严格。在 C 中,任何非 0 都是真的,所以你可以测试 if (IsAlphabetical(token) != 0) 或只是 if (IsAlphabetical(token))

  • 为什么要分配一个字符串的副本传递给AddWords(&words, string);,然后再传递给free(string)?如果Addwords() 没有保留它得到的指针,则不需要分配副本。

  • AddWords() 是否调用 strtok()strtok() 是不可重入的,这意味着如果AddWords() 或在此循​​环中调用的任何其他函数,例如IsAlphabetical() 调用strtok(),则循环中使用的上下文将被破坏。你应该改用strtok_r()

  • 在函数DeleteData,为什么要迭代测试while (temp->pNext != NULL)?列表中的最后一项没有被正确释放,DeleteWords(&temp->words); 没有被调用。 这可能会导致内存泄漏。你应该写:

      void DeleteData(Data **head) {
          Data *temp = *head;
          while (temp != NULL) {
              Data *next = temp->pNext;
              DeleteWords(&temp->words);
              free(temp);
              temp = next;
          }
          *head = NULL;
      }
    

【讨论】:

  • 我们可以进行任何形式的聊天吗?比如信使什么的?这是更大的事情:/
  • @Cris:对不起,但不是现在,我必须做一些错误。发布 cmets,我将尝试解决其他更大的问题。
  • 我将在下面发布一个答案,因为我想分享我的部分代码,让我秒
  • 答案在上面
  • @Cris: 在AddWords 中,您必须在循环中测试temp->pNext != NULL 以定位列表中的最后一个节点。如果你只是测试temp != NULL,循环后temp 将是NULL。相反,在DeleteData 中,您必须释放每个 节点,因此您必须迭代直到tempNULL
猜你喜欢
  • 2020-09-22
  • 1970-01-01
  • 1970-01-01
  • 2011-02-18
  • 2022-07-30
  • 1970-01-01
  • 1970-01-01
  • 2019-10-06
  • 1970-01-01
相关资源
最近更新 更多