记忆泄漏,我似乎无法找到原因

时间:2013-10-21 18:55:09

标签: c memory heap memory-leaks

所以我正在编写一个用于管理堆数据结构的程序。我制作了两个动态内存分配,并且(我认为)当我收尾时我正确地释放它们。

#include "heapFunctions.h"
#include "util.h"
#include <stdio.h>
#include <stdlib.h>

//Function Prototypes
static element* getArray(int*);

int main(void){
int result=0;
int i,v;
heap myHeap;
myHeap.H = NULL;
int arrayLength;
element* myArray = NULL;
char menuSelection = nextCommand(&i,&v);        //get selection from user
while(!(menuSelection == 'S' || menuSelection == 's')){
    switch(menuSelection){
        case 'c':
        case 'C':
            if(myHeap.H == NULL)
                myHeap = initialize(i);         //initialize heap and identify any errors
            else{
                free(myHeap.H);
                myHeap=initialize(i);
            }
            if(myHeap.H != NULL)
                printf("Command Entered %c. Heap Initialized with capacity %d\n", menuSelection, i);
            else
                printf("Command Entered %c. Heap space not allocated\n", menuSelection);
            break;
        case 'r':
        case 'R':
            if(myArray == NULL)
                myArray = getArray(&arrayLength);               //populate array from text file
            else{
                free(myArray);
                myArray = getArray(&arrayLength);
            }
            result=buildHeap(&myHeap, myArray, arrayLength);        //build heap with array
            if(result==1)
                printf("Command Entered %c. Heap was built with size %d\n", menuSelection, arrayLength);
            else if (result == -1)
                printf("Command Entered %c. Heap build was unsuccesful\n", menuSelection);
            else if (result == -2)
                printf("Command Entered %c. Heap capacity can't accomodate array\n", menuSelection);
            break;
        case 'w':
        case 'W':
            printf("Command Entered %c. Printing Heap\n", menuSelection);
            printHeap(&myHeap);                 //print contents of heap
            break;
        case 'i':
        case 'I':
            result = insert(&myHeap, i);            //insert new key i into heap
            if (result == 1)
                printf("Command Entered %c. Heap insert with key %d was succesful\n", menuSelection, i);
            else
                printf("Command Entered %c. Heap insert was unsuccesful\n", menuSelection);
            break;
        case 'd':
        case 'D':
            result = deleteMax(&myHeap);        //extract max value from heap
            if (result > 0)
                printf("Command Entered %c. Deletion of max heap value %d was succesful\n", menuSelection, result);
            break;
        case 'k':
        case 'K':
            result = increaseKey(&myHeap, i, v);            //increase key at index i to v
            if(result == 1)
                printf("Command Entered %c. Key was succesfully increased to %d at index %d\n", menuSelection, v, i);
            else if(result == -1)
                printf("Command Entered %c. Key increase failed, %d not a valid index\n", menuSelection, i);
            else if (result == -2)
                printf("Command Entered %c. Key increase failed, %d is not larger than current key\n", menuSelection, v);
            else if (result == -3)
                printf("Command Entered %c. Key increase failed, Index starts at 1!", menuSelection);
    }
    menuSelection = nextCommand(&i,&v); 
}
printf("You have entered command %c and stopped the program.\n", menuSelection);

//free resources
free(myArray);
free(myHeap.H);
return 1;
}

//get array from text file for heap
static element* getArray(int *Length){
    element *arrayKey;          //declare pointer for new array
    int arrayLength=0;
    char inputBuffer[10];
    FILE *fp;
    fp = fopen("HEAPinput.txt","r");            //open text file
    if (fp == NULL){                    /*check to make sure file was opened*/
        fprintf(stderr, "Cannot open input file!!\n");
        exit(1);
    }
    if(fgets(inputBuffer, sizeof(inputBuffer), fp) != NULL){        //get line of text
        sscanf(inputBuffer, "%d", &arrayLength);                //parse line for number of inputs
    }

    if(arrayLength < 1){                //error if array length is invalid
        printf("Invalid Array Length\n");
        exit(1);
    }

    arrayKey = (element *) malloc(sizeof(element)*arrayLength);     //dynamically allocate memory for values
    if(arrayKey == NULL){
        printf("Memory for array not allocated\n");
         exit(1);
    }   
    int count;

    for (count =0; count < arrayLength; count++){               //populate array with input from file
        fscanf(fp, "%d", &arrayKey[count].key);
    }

    *Length = arrayLength;  
    fclose(fp);                                             //close file
    return arrayKey;                        //return array      
}


//initialize new heap with size 0 and designated capacity
heap initialize(int capacity){
    heap myHeap;
    myHeap.size = 0;
    myHeap.capacity = capacity;
    myHeap.H = (element*) malloc(sizeof(element)*capacity);         //dynamically allocate memory blocks for heap with designated capacity
    return myHeap;
}

//copy contents of heap into H element,
int buildHeap(heap *myHeap, element * myArray, int arrayLength){
    if(arrayLength > myHeap->capacity)      //error if capacity is to small
        return -2;
    if(myHeap->H == NULL)
        return -3;
    if(memcpy(myHeap->H, myArray, sizeof(element)*arrayLength) == NULL)     //error if memory not allocated properly
        return -1;

    myHeap->size=arrayLength;               //set size to arrayLength

    int count=0;
    for(count=(arrayLength/2); count >= 0; count--){            //buildHeap
        heapify(myHeap, count);
    }
    return 1;

}

我不确定这是如何工作的,我试着发布我认为是必要的代码片段。我只在两个位置动态分配内存,我认为在离开main之前我已正确释放它们。我不知道我还能在哪里泄漏。

我使用了valgrind并得到了错误

 LEAK SUMMARY:
 ==4042==    definitely lost: 13,546 bytes in 70 blocks
 ==4042==    indirectly lost: 53 bytes in 5 blocks
 ==4042==      possibly lost: 29 bytes in 2 blocks
 ==4042==    still reachable: 33,958 bytes in 53 blocks

我还打印了整个跟踪(带有调试符号),但所有输出几乎相同(对于大多数块重复以下内容)。我尝试使用带有-g标志和fulltrace的valgrind使用gcc + g ++进行编译但是我仍然只是得到了???对于mem位置后的输出。

==5804== 3 bytes in 1 blocks are possibly lost in loss record 2 of 97
==5804==    at 0x4C2C73C: malloc (vg_replace_malloc.c:270)
==5804==    by 0x440137: ??? (in /usr/bin/g++-4.7)
==5804==    by 0x43CDEB: ??? (in /usr/bin/g++-4.7)
==5804==    by 0x414C80: ??? (in /usr/bin/g++-4.7)
==5804==    by 0x41592F: ??? (in /usr/bin/g++-4.7)
==5804==    by 0x40296E: ??? (in /usr/bin/g++-4.7)
==5804==    by 0x4E5576C: (below main) (libc-start.c:226)


349 (320 direct, 29 indirect) bytes in 2 blocks are definitely lost in loss record          73 of 96
==4098==  at 0x4C2C92E: realloc (vg_replace_malloc.c:662)

任何人都可以指出我正确的方向,为什么我泄漏记忆。

1 个答案:

答案 0 :(得分:3)

这是一次泄密:

case 'R':
    myArray = getArray(&arrayLength);               //populate array from text file

我不确定执行“R”菜单选择的次数,但{while}循环中永远不会释放myArray。每次执行此选择时,您都会泄漏先前指向的内存myArray。退出while循环后,您只释放已分配的最后一个内存位置。

与'C'相同:

case 'C':
    myHeap = initialize(i);         //initialize heap and identify any errors

如果多次执行此操作,则会泄漏myHeap以前指向的内存。退出循环后,您只释放分配给myHeap.H的最后一个内存位置。

<强>更新

使用您的最新更新,您现在需要初始化变量。因为他们住在堆栈上,他们可能包含垃圾。例如,第一次检查myArray == NULL时,它可能会返回false,导致您尝试释放尚未分配的内存。

heap myHeap;
myHeap.H = NULL;

element* myArray = NULL;