【问题标题】:Memory leak while using linked lists and hash arrays使用链表和哈希数组时的内存泄漏
【发布时间】:2012-05-07 01:05:10
【问题描述】:

无论我做什么,我都不知道为什么会泄漏内存。我正在释放所有动态创建的内存,但它说我有 406 个泄漏。任何提示都会很棒。我花了一周的时间试图弄清楚并使用crtdbg(不显示任何线条)和VLD,但仍然没有运气。抱歉,代码太长了:

---------- Block 742 at 0x00F06D50: 56 bytes ----------
Call Stack:
c:\users\main\desktop\lab3123.c (113): lab3.exe!createNode + 0xA bytes
c:\users\main\desktop\lab3123.c (152): lab3.exe!addToArr + 0x9 bytes
c:\users\main\desktop\lab3123.c (66): lab3.exe!main + 0x10 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): lab3.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): lab3.exe!mainCRTStartup
0x76713677 (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
0x775B9F42 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
0x775B9F15 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
Data:
74 65 63 68    6E 6F 6C 6F    67 79 00 CD    CD CD CD CD     technolo gy......
CD CD CD CD    CD CD CD CD    CD CD CD CD    CD CD CD CD     ........ ........
CD CD CD CD    CD CD CD CD    CD CD CD CD    CD CD CD CD     ........ ........
CD CD CD CD    01 00 00 00                                   ........ ........


---------- Block 746 at 0x00F06E20: 56 bytes ----------
Call Stack:
c:\users\main\desktop\lab3123.c (113): lab3.exe!createNode + 0xA bytes
c:\users\main\desktop\lab3123.c (152): lab3.exe!addToArr + 0x9 bytes
c:\users\main\desktop\lab3123.c (66): lab3.exe!main + 0x10 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (555): lab3.exe!__tmainCRTStartup + 0x19 bytes
f:\dd\vctools\crt_bld\self_x86\crt\src\crtexe.c (371): lab3.exe!mainCRTStartup
0x76713677 (File and line number not available): kernel32.dll!BaseThreadInitThunk + 0x12 bytes
0x775B9F42 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x63 bytes
0x775B9F15 (File and line number not available): ntdll.dll!RtlInitializeExceptionChain + 0x36 bytes
Data:
68 75 6D 61    6E 69 74 79    00 CD CD CD    CD CD CD CD     humanity ........
CD CD CD CD    CD CD CD CD    CD CD CD CD    CD CD CD CD     ........ ........
CD CD CD CD    CD CD CD CD    CD CD CD CD    CD CD CD CD     ........ ........
CD CD CD CD    01 00 00 00                                   ........ ........


Visual Leak Detector detected 406 memory leaks (26480 bytes).
Largest number used: 43684 bytes.
Total allocations: 57944 bytes. 
Visual Leak Detector is now exiting.
Press any key to continue . . .
WORDNEW* createNode(char *str)
{
    WORDNEW* w;

    if(!(w = (WORDNEW*)malloc(sizeof(WORDNEW))))
        printf("Memory Allocation Error"),
            exit(100);
    strcpy(w->str, str);
    w->count = 1;
    return w;
}

//addToArr: adds a word to the hash array or linked list if there is a collision
void addToArr( char *str, HASH_ARR_ELEM hashArr[]){
    int homeAddress = 0;
    int addResult = 0;
    int probe = 0;
    HASH_ARR_ELEM *ph;
    WORDNEW *w;
    WORDNEW *rWord;
    rWord = NULL;
    homeAddress = hashFunct(str);
    ph = &hashArr[homeAddress];

    if(ph->wordPtr == NULL){
        if(!(ph->wordPtr = (WORDNEW*)malloc(sizeof(WORDNEW))))
            printf("Memory Allocation Error"),
                exit(100);
        strcpy(ph->wordPtr->str, str);
        ph->wordPtr->count = 1;
    }else if(ph->wordPtr != NULL && ph->headPtr == NULL){
        if(!(strcmp(ph->wordPtr->str, str)))
            ph->wordPtr->count++;
        else {
            ph->headPtr = createList(cmpWord);
            w = createNode(str);
            addNode(ph->headPtr,w,&probe);
        }
    }else {
        w = createNode(str);
        if(!(strcmp(ph->wordPtr->str, str))){
            ph->wordPtr->count++;
            free(w);
        }else if(retrieveNode(ph->headPtr,w,&rWord,&probe) == 1){
            rWord->count++;
            free(w);
        }else
            addNode(ph->headPtr,w,&probe);
    } //end else


} // end addToArr

【问题讨论】:

  • 听到提示。让你的程序足够小,这样你就没有内存泄漏,如果需要的话,一直到一个空的主程序。然后逐渐添加回你认为不应该泄漏的东西。观察导致泄漏的原因。
  • 是否 (WORDNEW*)malloc(sizeof(WORDNEW)) 曾经被释放?
  • 另一个提示是发布更少的代码。我不知道有多少人从 SO 问题中编译每段代码,但我尝试对其进行审查。更短的代码更容易和更快地审查。
  • Alex 很抱歉,但我想我会帮忙的。
  • That's really a lot of code to wade through. 作为一般调试技巧,我会建议与@DougT 相同的事情。做到了:使您的程序足够小,以使其没有泄漏。或者,您可以使用 Valgrind 之类的内存分析器。

标签: c memory-leaks linked-list frequency


【解决方案1】:

从上面,我推测您认为错误出现在 addToArr 中。以下是一些查找故障的建议。

  • 删除 tempWord。仅使用 str 字段,这是 str 调用参数的副本。所以只要有tempWord->str,就使用str

  • 然后,如果您可以控制 addNode 的代码,请在其中进行必要的分配。

  • 否则,将对 addNode 的调用包装在一个分配 WORDNEW 结构的函数中,将 str 复制到其中并将 count 设置为 1,然后将其传递给 addNode。

您还可以:

  • 通过分解重复部分来重写 if-the-else 链。
  • 使用指针ph-> 分解出重复的hashArr[homeAddress].

    HASH_ARR_ELEM *ph = &hashArr[homeAddress];

  • 打开编译器警告以警告您有关模棱两可的“else”子句。具体来说,您有:

     if (!strcmp...)){
          ...
     }else
     {
         ...
         if(addResult != 0)
             if(addResult == -1){
                 printf("Memory Overflow adding node\n"),
                 exit(120);
             }else{
                 etc...
             }
    

EDIT 2(重构 addToArr 之后)

该功能现在看起来好多了,尽管仍有一些可能的改进点并且一些错误检查已经消失。但是,如果您仍然有泄漏,那么它不在 addToArr 中。什么或谁告诉你有 406 泄漏?

现在的改进包括:

  • (ph->wordPtr != NULL) 是不必要的,因为您从上述条件中知道ph->wordPtr == NULL

  • 以下位对于两个主要的 else 子句都是通用的,并且可以只执行一次:

    if (!strcmp(ph->wordPtr->str, str))
         ph->wordPtr->count++;
    
  • 在失败时使用 perror 而不是 printf

  • 在调用参数之间以及elseif周围添加空格

  • 移除 malloc return 的演员表

  • 去掉括号加空格:if(!(strcmp(...)))变成if (!strcmp(...))

  • cmpWord 未定义。

【讨论】:

  • 好的,这就是我根据您的建议所做的,但仍然是一样的。请看上面的代码(重新编辑了原贴)
  • 威廉感谢您的提示。我真的很感激。 Visual Leak Detector 告诉我我有 406 次泄漏。
  • 我想知道 Visual Leak Detector 认为泄漏是什么。它有什么线索吗? “泄漏”的数量是否与哈希数组中的条目数量相对应?
  • 它显示的泄漏看起来像存储在链表中的信息。我使用函数 destroyList() 来释放内存并销毁列表,但它仍然显示为泄漏。我重新编辑了上面的原始帖子以显示内存泄漏。
  • 泄漏可能在 addNode 和 retrieveNode 中吗?你有这些函数的源代码吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-10-09
  • 1970-01-01
  • 2012-03-15
  • 1970-01-01
  • 1970-01-01
  • 2018-06-26
  • 2017-09-26
相关资源
最近更新 更多