【问题标题】:Cannot find the memory leak. Staring for 1 hour找不到内存泄漏。凝视1小时
【发布时间】:2015-04-11 17:35:29
【问题描述】:

以下 C 代码存在内存泄漏。我盯着它看了一个小时,但找不到它。我已经能够将其缩小到该功能,但仍然没有改进的运气。

你能帮我找到吗?

感谢任何帮助。谢谢!

void insert ( LISTNODEPTR *sPtr, char value[SIZE] ) {
    LISTNODEPTR newPtr, previousPtr, currentPtr;
    int cmp;

    newPtr = malloc(sizeof(LISTNODE));

    if ( newPtr != NULL ) {

        newPtr->data = malloc(sizeof(SIZE));

        strcpy(newPtr->data, value);
        newPtr->nextPtr = NULL;

        previousPtr = NULL;
        currentPtr = *sPtr;

        /* Comparision to detect & remove duplicates nodes */
        while ( currentPtr != NULL ) {
            cmp = strcmp(value, currentPtr->data);
            if (cmp < 0) {
                /* you're at the point where you need to add the node */
                break;
            } else if (cmp == 0) {
                /* value is equal, no duplicate is allowed, leave */

                // since it is not added, destroy!
                free(newPtr->data);
                free(newPtr);

                return;
            }

            previousPtr = currentPtr;
            currentPtr = currentPtr->nextPtr;
        }

            if ( previousPtr == NULL ) {
                newPtr->nextPtr = *sPtr;
                *sPtr = newPtr;
            }
            else{
                previousPtr->nextPtr = newPtr;
                newPtr->nextPtr = currentPtr;
            }

    }


}

编辑:

更多代码:

#define SIZE 1001

struct listNode {
    char *data;
    struct listNode *nextPtr;
};

typedef struct listNode LISTNODE;
typedef LISTNODE *LISTNODEPTR;

/* Function prototype */
void insert ( LISTNODEPTR *, char[SIZE] );

瓦尔格林:

==19906== LEAK SUMMARY:
==19906==    definitely lost: 12 bytes in 3 blocks
==19906==    indirectly lost: 0 bytes in 0 blocks
==19906==      possibly lost: 0 bytes in 0 blocks
==19906==    still reachable: 0 bytes in 0 blocks
==19906==         suppressed: 0 bytes in 0 blocks

如果我将 sizeof(SIZE) 转换为 SIZE,那么内存泄漏将变为 +3000。

编辑 2:

我确实在 main() 中释放它们

while ( startPtr != NULL ){
    LISTNODEPTR tmp = startPtr;
    startPtr = startPtr->nextPtr;
    free(tmp);
}   

【问题讨论】:

  • 你怎么知道有内存泄漏?和malloc(sizeof(SIZE)); 你确定吗?
  • 这里的SIZE 是什么? newPtr-&gt;data = malloc(sizeof(SIZE));
  • 很确定应该是 malloc(SIZE)。如果它是一个宏,你当前的malloc(sizeof(SIZE)) 将 malloc 的大小为int(我没有理由认为它不是)。因此,除非您要复制的字符串在 32 位 int 实现上是 3 个字符长或更短,否则您将使用该 strcpy 调用未定义的行为。
  • 顺便说一句,使用 Valgrind 的道具。
  • 我不在乎尺寸损失的增加。之前的代码完全错误,需要修复。您的实际泄漏是由于您未能在 free 中的节点指针之前释放数据块。最后,您在执行此操作时不需要所有额外的指针杂耍。传递给您的函数的指针对指针几乎可以轻松完成所有这些工作。 see example.

标签: c pointers memory memory-leaks valgrind


【解决方案1】:

您释放了节点,但没有释放数据。

while ( startPtr != NULL ){
    LISTNODEPTR tmp = startPtr;
    startPtr = startPtr->nextPtr;
    free(tmp->data);     // Line added
    free(tmp);
}   

【讨论】:

  • 我猜这是我发布答案后添加的!
  • 骗我!对于那个很抱歉。谢谢
【解决方案2】:

存在内存泄漏,因为您在函数中本地分配的指针永远无法从函数外部访问。

同样malloc(sizeof(SIZE))是错误的,你应该把它改成malloc(SIZE),如果它是一个固定值,你应该把data成员声明为char data[SIZE]而不是malloc()ing空间。

简短回答

内存泄漏是由于您的程序不是free()ing malloc()ed 内存。

【讨论】:

  • 当我成功时malloc(SIZE), definitely lost: 3,003 bytes in 3 blocks
  • 如上所述,free 你的malloc-ed 空间使用后。
  • @user4220128 使用 valgrind 确实是一件好事,但看来你需要了解malloc()/free() 是如何工作的。
  • @user4220128:因为你似乎一直在使用 Valgrind:当你使用 --leak-check=full 时,Valgrind 会告诉你 mallocs 没有匹配 frees 出现在哪里。
【解决方案3】:

简化:

  • value[SIZE] 参数更改为 char*,因为它就是这样
  • 没有令人困惑(且不可见)的 typedef
  • malloc() 只有在您知道您确实需要新节点时才会调用
  • 删除了由于不使用指向指针结构的指针而导致的过多变量和条件
  • 使用 strdup(),因为这样更简单

struct listnode {
        struct listnode *nextPtr;
        char *data;
        };

void insert ( struct listnode **pp, char *value ) {
    struct listnode *newPtr;
    int cmp;

        /* find place to insert in LL */
    while ( *pp) {
        /* Comparision to detect & remove duplicates nodes */
            cmp = strcmp(value, (*pp)->data);
                /* Duplicate: nothing to do ... */
            if (cmp == 0) return;
                /* you're at the point where you need to add the node */
            if (cmp < 0) break;
            pp = &(*pp)->nextPtr;
            }

    /* when you get here, *pp points to the pointer you want to change.
    ** *pp could even be NULL (if we are at the end of the list)
    */

    newPtr = malloc(sizeof *newPtr);    
    if ( !newPtr ) { barf(); return; }

    newPtr->data = strdup (value);
        /* you could check newPtr->data here, and if null: free(newPtr) */

        /* "steal" the pointer */
    newPtr->nextPtr = *pp;
        /* and inject the new pointer into the LL */
    *pp = newPtr;
    return;
}

【讨论】:

猜你喜欢
  • 2018-04-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多