为什么会发生这种内存泄漏

时间:2021-05-27 10:31:53

标签: c memory-leaks valgrind

我在 valgrind 中遇到此错误

==399==ERROR: LeakSanitizer: detected memory leaks
 Direct leak of 240 byte(s) in 15 object(s) allocated from:
     #0 0x7f2a8cfadb50 in __interceptor_malloc (/usr/lib/x86_64-linux-gnu/libasan.so.4+0xdeb50)
     #1 0x401371 in push /src/main.c:88
     #2 0x401725 in buildTree /src/main.c:126
     #3 0x4027e1 in encode /src/main.c:31
     #4 0x402c8b in main /src/main.c:432
     #5 0x7f2a8c761b96 in __libc_start_main (/lib/x86_64-linux-gnu/libc.so.6+0x21b96)

我的推送功能:

void push(Heap* heap, Node* node) {
    if (heap->heapSize + 1 >= heap->capacity) {
        int capacity_ = heap->capacity * 2;
        qNode** arr_ = realloc(heap->arr,sizeof(qNode) *  capacity_);
        heap->arr = arr_;
        heap->capacity = capacity_;
    }
    heap->arr[heap->heapSize] = (qNode*) malloc(sizeof(qNode)); //line 88, where the leak occurs
    heap->arr[heap->heapSize]->data = node;
    heap->arr[heap->heapSize]->priority = node->count;
    heap->heapSize = heap->heapSize + 1;
    for (int i = (heap->heapSize/2)-1; i > -1; i--) {
        heapify(heap, i);
    }
}

我不明白为什么会发生泄漏,因为在程序结束时我清除了整个堆->arr

void freeHeap(Heap* heap) {
    for (int i = 0; i < heap->heapSize; i++) {
        freeTree(heap->arr[i]->data);
        free(heap->arr[i]);
    }
    free(heap->arr);
    free(heap);
}

Entire code

1 个答案:

答案 0 :(得分:2)

当您在完整程序中看到运行 pop() 时,指向先前由 heap->arr[0] 指向的 qNode 的唯一指针在 pop() 的返回值中传回。

qNode* pop(Heap* heap)
{
    qNode* result = heap->arr[0];
 
    heap->arr[0] = heap->arr[heap->heapSize - 1];
    heap->heapSize = heap->heapSize - 1;
 
    heapify(heap, 0);
    return result;
}

这意味着 pop() 的调用者现在持有指向该 qNode 的最后一个指针,并且有义务确保在指针超出范围之前释放 qNode。

您的代码包含 pop() 调用方无法执行此操作的几个地方。这是来自 buildTree 的示例(显示的最后一行)。当 buildTree 返回时 qNode 被泄漏,因为现在不再有任何指向该 qNode 的指针。

Node* buildTree(Heap* heap, int* tab) {
    for (int i = 0; i < 256; ++i) {
        if (tab[i]) {
            Node* node = createNode(tab[i], i, NULL, NULL);
            push(heap, node);.
    
    
        }
    }
     
    if (heap->heapSize == 1) {
        return pop(heap)->data;