简体   繁体   中英

Valgrind error when using malloc

I am using valgrind to fix memory leaks in my C program, and there is one particular function that seems to be the source of most of the valgrind errors

typedef struct Array {
    int capacity;
    int size;
    void **items;
} Array;

Array *createArray(int capacity) {
    Array *array = malloc(sizeof(Array));
    array->capacity = capacity;
    array->size = 0;
    void **items = malloc(sizeof(void *) * array->capacity *  sizeof *items);
    if(items == NULL) {
        exit(1);
    }
    array->items = items;
    return array;
}

The first line of the createArray function is throwing the following error in Valgrind

1,296 (16 direct, 1,280 indirect) bytes in 1 blocks are definitely lost in loss record 34 of 42

Am I not using malloc in the right way to allocate memory?

As discussed above in the comments, it is unclear why you allocate items with:

 void **items = malloc(sizeof(void *) * array->capacity *  sizeof *items);

(which essentially allocates 8x (an additional multiple of sizeof "a pointer" ) number of pointers than would be required)

Instead, if you are allocating array->capacity pointers for items , then use:

void **items = malloc(array->capacity * sizeof *items);

Your valgrind error does not look like an error, but the result of not calling free on the memory you allocate, leaving valgrind to report the bytes lost (still reachable on exit). You can easily free the memory on exit with a simple destroyArray function similar to:

void destroyArray (Array *array) {
    for (int i = 0; i < array->size; i++)
        free (array->items[i]);
    free (array->items);
    free (array);
}

Putting it altogether you could do something like:

#include <stdio.h>
#include <stdlib.h>

typedef struct Array {
    int capacity;
    int size;
    void **items;
} Array;

Array *createArray (int capacity) {
    Array *array = malloc (sizeof *array);
    array->capacity = capacity;
    array->size = 0;
    void **items = malloc(array->capacity *  sizeof *items);
    if(items == NULL) {
        exit(1);
    }
    array->items = items;
    return array;
}

void destroyArray (Array *array) {
    for (int i = 0; i < array->size; i++)
        free (array->items[i]);
    free (array->items);
    free (array);
}

int main (void) {

    Array *a = createArray (10);
    printf ("%d capacity\n", a->capacity);
    destroyArray (a);

    return 0;
}

( note: you should also validate Array *array = malloc (sizeof *array); succeeded and (array != NULL) before attempting to use array )

Memory Use/Error Check

$ valgrind ./bin/allocstruct
==5777== Memcheck, a memory error detector
==5777== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==5777== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==5777== Command: ./bin/allocstruct
==5777==
10 capacity
==5777==
==5777== HEAP SUMMARY:
==5777==     in use at exit: 0 bytes in 0 blocks
==5777==   total heap usage: 2 allocs, 2 frees, 96 bytes allocated
==5777==
==5777== All heap blocks were freed -- no leaks are possible
==5777==
==5777== For counts of detected and suppressed errors, rerun with: -v
==5777== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

Look things over and let me know if this is what you were concerned with.

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