简体   繁体   中英

How can I fix the memory leaks of this program, when I know what it leaks, most of the times?

So, I have a dynamic array which leaks memory and I can almost always find out that all memory lost is lost in ONE block, and sometimes it didn't leak anything. However, I changed something, and now it always leaks, but it's a computable sum (I think it's the size of the array we last get before quitting the program). Can you please help me with this?

Here's the code if you want to look into it:

#include "DynamicVector.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>

DynamicVector createDynamicVector() {
    DynamicVector dynamicVector;
    dynamicVector.number_of_elements = 0;
    dynamicVector.capacity = 2;
    dynamicVector.elements = (int *)malloc(dynamicVector.capacity * sizeof(int));
    return dynamicVector;
}

int isEmpty(DynamicVector *pointer) {
    if (pointer->number_of_elements == 0)
        return 1;
    return 0;
}

int search_element(DynamicVector *pointer, int element) {
    int index;
    for (index = 0; index < pointer->number_of_elements; index++) {
        if (pointer->elements[index] == element) {
            return index;
        }
    }
    return -1;
}

void resize_smaller(DynamicVector *pointer) {
    int *new_elements;
    new_elements = (int *)malloc((pointer->capacity * 3 / 4) * sizeof(int));
    memcpy(new_elements, pointer->elements, pointer->number_of_elements * sizeof(int));

    destroyDynamicVector(pointer);
    pointer->elements = new_elements;
    pointer->capacity = pointer->capacity * 3 / 4;
}

void resize_bigger(DynamicVector *pointer) {
    int *new_elements;
    new_elements = (int *)malloc(pointer->capacity * 2 * sizeof(int));
    memcpy(new_elements, pointer->elements, pointer->number_of_elements * sizeof(int));
    destroyDynamicVector(pointer);
    pointer->elements = new_elements;
    pointer->capacity = pointer->capacity * 2;
}

void add_element(DynamicVector *pointer, int element) {
    if (pointer->capacity == pointer->number_of_elements) {
        resize_bigger(pointer);
    }
    *(pointer->elements + pointer->number_of_elements) = element;
    pointer->number_of_elements++;
}

int remove_element(DynamicVector *pointer, int element) {
    int index_found = 0;
    index_found = search_element(pointer, element);
    if (index_found == -1) {
        return 1;
    }
    *(pointer->elements + index_found) = *(pointer->elements + pointer->number_of_elements - 1);
    pointer->number_of_elements--;
    if (pointer->number_of_elements < pointer->capacity / 2) {
        resize_smaller(pointer);
    }
    return 0;
}

void destroyDynamicVector(DynamicVector *pointer) {
    free(pointer->elements);
}

The code seems fine, you should post the structure definition and a main() function that exhibits the leak . It is possible that this leak be unrelated to your code: also explain what tool you are using to detect memory leaks.

There is a small issue for huge vector sizes where pointer->capacity * 3 / 4 might cause an integer overflow. This overflow could cause the malloc() to fail and return NULL , prompting undefined behavior when copying the array contents.

You could also use realloc() instead of malloc() for resizing, saving some copying if the block can be resized in place:

int resize_bigger(DynamicVector *pointer) {
    size_t new_capacity = pointer->capacity * 2;
    int *new_elements = realloc(pointer->elements, new_capacity * sizeof(int));
    if (new_elements != NULL) {
        pointer->elements = new_elements;
        pointer->capacity = new_capacity;
        return 0;
    } else {
        return -1;
    }
}

void resize_smaller(DynamicVector *pointer) {
    size_t new_capacity = pointer->capacity - pointer->capacity / 4;
    int *new_elements = realloc(pointer->elements, new_capacity * sizeof(int));
    if (new_elements != NULL) {
        pointer->elements = new_elements;
        pointer->capacity = new_capacity;
    }
}

// return the element number or -1 in case of failure
int add_element(DynamicVector *pointer, int element) {
    if (pointer->capacity == pointer->number_of_elements) {
        if (resize_bigger(pointer))
            return -1;
    }
    pointer->elements[pointer->number_of_elements] = element;
    return pointer->number_of_elements++;
}

When you add element, you multiply size by 2 but when you remove element ou keep 3/4. That means that after adding one element and removing element the size will be 2*3/4=1.25 the original size.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM