使用链接列表和哈希数组时内存泄漏

时间:2012-05-07 01:05:11

标签: c memory-leaks linked-list frequency

无论我做什么,我都不知道为什么这会泄漏记忆。我正在释放所有动态创建的内存,但它说我有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

1 个答案:

答案 0 :(得分:0)

从上面,我收集你认为错误在addToArr。以下是找出错误的一些建议。

  • 删除tempWord。仅使用str字段,这是str调用参数的副本。因此,只要您str使用tempWord->str

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

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

您可能也会:

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

    HASH_ARR_ELEM * ph =& hashArr [homeAddress];

  • 打开编译器警告,警告您有关模糊的“其他”条款。具体来说,你有:

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

编辑2(重构addToArr之后)

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

现在改进包括:

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

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

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

  • 在通话参数与elseif

  • 附近添加空格
  • 删除malloc return的转换

  • 删除括号并添加空格:if(!(strcmp(...)))变为if (!strcmp(...))

  • cmpWord未定义。