【问题标题】:C - Can't get rid of memory leaksC - 无法摆脱内存泄漏
【发布时间】:2020-09-22 06:08:08
【问题描述】:

我做了一个程序,它从一个文件中读取单词,对它们进行排序并插入到列表中,然后我将列表打印到新文件中。单词必须按字母顺序排序。我使用 strcmp() 函数来比较它们,并创建了函数 MakeLowerCase()。它将字符串“转换”为小写字符串。我知道该程序进行了很多操作,但我不知道如何优化它。无论如何,我必须摆脱内存泄漏,但我不知道它泄漏在哪里。

我从 Dr Memory 那里得到了这样的报告(只是其中的一部分):


error #5: LEAK 2 direct bytes 0x01373d60-0x01373d62 + 0 indirect bytes
# 0 replace_malloc                     [d:\drmemory_package\common\alloc_replace.c:2577]
# 1 msvcrt.dll!_strdup   
# 2 .text      
# 3 __mingw_glob
# 4 _setargv   
# 5 .text      
# 6 ntdll.dll!__RtlUserThreadStart

Error #6: LEAK 11 direct bytes 0x01373db0-0x01373dbb + 0 indirect bytes
# 0 replace_malloc               [d:\drmemory_package\common\alloc_replace.c:2577]
# 1 MakeItTxt  
# 2 main       

Error #7: LEAK 6 direct bytes 0x01374f10-0x01374f16 + 0 indirect bytes
# 0 replace_malloc                    [d:\drmemory_package\common\alloc_replace.c:2577]
# 1 MakeLowerCase
# 2 sortedInsert
# 3 InsertWordsToStruct
# 4 main       

Error #8: LEAK 6 direct bytes 0x01374f38-0x01374f3e + 0 indirect bytes
# 0 replace_malloc                    [d:\drmemory_package\common\alloc_replace.c:2577]
# 1 MakeLowerCase
# 2 sortedInsert
# 3 InsertWordsToStruct
# 4 main       

Error #9: LEAK 4 direct bytes 0x013750a0-0x013750a4 + 0 indirect bytes
# 0 replace_malloc                    [d:\drmemory_package\common\alloc_replace.c:2577]
# 1 MakeLowerCase
# 2 sortedInsert
# 3 InsertWordsToStruct
# 4 main       

Error #10: LEAK 6 direct bytes 0x013750c8-0x013750ce + 0 indirect bytes
# 0 replace_malloc                    [d:\drmemory_package\common\alloc_replace.c:2577]
# 1 MakeLowerCase
# 2 sortedInsert
# 3 InsertWordsToStruct
# 4 main       

Reached maximum leak report limit (-report_leak_max). No further leaks will be reported.

===========================================================================
FINAL SUMMARY:

DUPLICATE ERROR COUNTS:
    Error #   1:      8
    Error #   2:      8
    Error #   4:      3
    Error #   7:    137
    Error #   8:    137
    Error #   9:   4855
    Error #  10:   4854

SUPPRESSIONS USED:

ERRORS FOUND:
      0 unique,     0 total unaddressable access(es)
      3 unique,    17 total uninitialized access(es)
      0 unique,     0 total invalid heap argument(s)
      0 unique,     0 total GDI usage error(s)
      0 unique,     0 total handle leak(s)
      0 unique,     0 total warning(s)
      7 unique,  9988 total,  68700 byte(s) of leak(s)
      0 unique,     0 total,      0 byte(s) of possible leak(s)
ERRORS IGNORED:
     10 unique,    12 total,    421 byte(s) of still-reachable allocation(s)

我可以与您分享我的部分代码(报告中的函数):


char* MakeLowerCase(char* word)
{
  char* lower = (char *)malloc(sizeof(char)*strlen(word)+1);
  strcpy(lower, word);
  int i = 0;

  for(i = 0; i < strlen(lower); i++){
    lower[i] = tolower(lower[i]);
  }
  return lower;
}

Word* newItem(char* word)
{
    /* allocate node */
    Word* new_item = (Word *)malloc(sizeof(Word));
    int word_length = strlen(word);
    new_item->word = (char *)malloc((word_length+1)*sizeof(char));

    strcpy(new_item->word, word);
    new_item->pNext = NULL;

    return new_item;
}

void sortedInsert(Word** pH, Word* new_node)
{
    Word* current;
    /* Special case for the head end */
    if (*pH == NULL || strcmp(MakeLowerCase((*pH)->word), MakeLowerCase(new_node->word)) == 1)
    {
        new_node->pNext = *pH;
        *pH = new_node;
    }
    else
    {
        /* Locate the node before the point of insertion */
        current = *pH;
        while (current->pNext!=NULL &&
               strcmp(MakeLowerCase(current->pNext->word), MakeLowerCase(new_node->word)) == -1)
        {
            current = current->pNext;
        }
        new_node->pNext = current->pNext;
        current->pNext = new_node;
    }
}

void InsertWordsToStruct(Word** pH, FILE* filename){
  char single_line[16384]; /* longest posible line in my code */

  int number_of_words = 0;
  int counter = 0;

  while(fgets(single_line, 16384, filename))
  {
    char* single_word = strtok(single_line, " \t\n\0"); /* cut one word from line */
    while(single_word != NULL)
    {
      if(IsLegitWord(single_word) == true) /* function return true if word is really word */
      {
        Word* new_node = newItem(single_word);
        sortedInsert(pH, new_node);
      }
      single_word = strtok(NULL, " \t\n\0");
    }
  }
}

我真的找不到漏洞。我是C新手,对不起。 当然,在我在 main 中使用的文件末尾:


RemoveWordList(&listname);

功能:


void RemoveWordList(Word** pH){
  Word* current = *pH;
  while (current != NULL){
      Word* next = current->pNext;
      free(current->word);
      free(current);
      current = next;
  }
  free(current);
  *pH = NULL;
}

^但我认为问题不在这里。^ 你有什么想法吗?你可以帮帮我吗?

【问题讨论】:

  • 您真的需要在MakeLowerCase 内复制吗?如果没有,那么您可以直接在传递的内存位置进行转换。
  • 我永远不会理解新程序员对链表的迷恋,你永远不会在实际的软件中使用它们,因为它们会完全杀死你的缓存,容易出错(一遍又一遍地证明)和很大,在内存方面。
  • @Blindy 当你还是一个新程序员的时候,你有没有实现过链表? :) 你说的是真的,但是它们确实具有有用的属性并且在很多场合都是有保证的。
  • @Blindy 这不是我的选择,只是学校的标准 :)

标签: c pointers memory struct memory-leaks


【解决方案1】:

根据 DNT 用户的建议,我重新制作了 sortedInsert() 函数。 现在它看起来像这样:


void sortedInsert(Word** pH, Word* new_node)
{
    Word* current;
    /* Special case for the head end */
    char* temp_word1 = MakeLowerCase((*pH)->word);
    char* temp_word2 = MakeLowerCase(new_node->word);
    if (*pH == NULL || strcmp(temp_word1, temp_word2 ) == 1)
    {
        new_node->pNext = *pH;
        *pH = new_node;
    }
    else
    {
        /* Locate the node before the point of insertion */
        current = *pH;
        while (current->pNext!=NULL &&
               strcmp(MakeLowerCase(current->pNext->word), MakeLowerCase(new_node->word)) == -1)
        {
            current = current->pNext;
        }
        new_node->pNext = current->pNext;
        current->pNext = new_node;
    }
    free(temp_word1);
    free(temp_word2);
}

内存泄漏减少了,但现在我的程序没有生成输出文件(可能出了点问题)。

【讨论】:

  • 好吧,你只修复了一个地方。还有其他地方,即使在这个新功能中,你仍然会这样做while (current-&gt;pNext!=NULL &amp;&amp; strcmp(MakeLowerCase(current-&gt;pNext-&gt;word), MakeLowerCase(new_node-&gt;word)) == -1),这也会泄漏内存。我建议你仔细检查你的整个代码。
  • 我知道,也有泄漏,但为什么我的程序停止工作?
  • @DNT 我们可以去任何类型的聊天,比如 messenger 之类的吗?如果你有时间
  • 你测试if (*pH == NULL ,但是现在添加temp_word代码之后,你之前没有测试它是否为NULL。检查我的答案,我在那里有评论。您需要更多地重构代码以更正逻辑并同时消除所有泄漏。
  • 让我等一下,我会试着弄清楚
【解决方案2】:

至少,这一行

if (*pH == NULL || strcmp(MakeLowerCase((*pH)->word), MakeLowerCase(new_node->word)) == 1)

由于MakeLowerCase 分配了从未释放的内存,因此不断泄漏内存。

考虑使用类似的东西

....
char *x1, *x2;
....
// add appropriate NULL checks here before proceeding
x1 = MakeLowerCase((*pH)->word);
x2 = MakeLowerCase(new_node->word);
if (*pH == NULL || strcmp(x1, x2) == 1)
....
free(x1);
free(x2);

检查您是否确实获得了您尝试分配的内存也是一个好习惯。

【讨论】:

  • 嗯,我该如何解决这个问题?
  • make variable char* x = MakeLowerCase((*pH)->word), if 之后释放它?
  • 不,现在我的程序不工作了。编译过程中没有错误但我没有输出文件
  • @Cris 我希望你没有逐字复制我的建议对吧?
  • 我可以回答我的问题并分享我的代码吗?或者在 stackoverflow 上不被禁止?
猜你喜欢
  • 2020-09-18
  • 2011-02-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-30
  • 1970-01-01
  • 2015-07-26
  • 2019-10-06
相关资源
最近更新 更多