Search code examples
c++memorymemory-leaksvalgrindfree

Valgrind, Blocks Are Definitely Lost even though I free?


Small Note, Please Ignore the use of malloc instead of new and the use of my own containers instead of vector etc... The point of this code was to practice the basics.

When I ran Valgrind I get:

==24855== HEAP SUMMARY:
==24855==     in use at exit: 0 bytes in 2 blocks
==24855==   total heap usage: 12,999 allocs, 12,997 frees, 675,432 bytes allocated
==24855==
==24855== 0 bytes in 1 blocks are definitely lost in loss record 1 of 2
==24855==    at 0x4C29F73: malloc (vg_replace_malloc.c:309)
==24855==    by 0x4014ED: ImageTagger::GetAllSegmentsByLabel(int, int**, int**, int*) (ImageTagger.cpp:100)
==24855==    by 0x402EB6: GetAllSegmentsByLabel (library2.cpp:59)
==24855==    by 0x403A8B: OnGetAllSegmentssByLabel (main2.cpp:345)
==24855==    by 0x4033A6: parser (main2.cpp:172)
==24855==    by 0x403135: main (main2.cpp:95)
==24855==

But the allocated block is freed in main, what's the problem? Here is the relevant part of my code:

ImageTagger.cpp:

StatusType ImageTagger::GetAllSegmentsByLabel(int label, int **images, int **segments, int *numOfSegments) {
    if (label <= 0 || images == nullptr || segments == nullptr || numOfSegments == nullptr) {
        return INVALID_INPUT;
    }
    *numOfSegments = Match_Num(image_tree->root, label);
    int *imageArr = (int *) malloc(sizeof(int) * (*numOfSegments));
    if (imageArr == nullptr) {
        return ALLOCATION_ERROR;
    }
    int *segArr = (int *) malloc(sizeof(int) * (*numOfSegments));
    if (segArr == nullptr) {
        free(imageArr);
        return ALLOCATION_ERROR;
    }
    int counter = 0;
    InorderTraversal(image_tree->root, imageArr, segArr, &counter, (*numOfSegments), label);
    *images = imageArr;
    *segments = segArr;
    if ((*numOfSegments) == 0) {
        *images = *segments = nullptr;
    }
    return SUCCESS;
}

And in main2.cpp I have (Notice both free lines at the end, how is that lost?):

static errorType OnGetAllSegmentssByLabel(void* DS, const char* const command) {
    int courseID, numOfLabels;
    int *images, *segments;
    ValidateRead(sscanf(command, "%d", &courseID), 1, "%s failed.\n", commandStr[GETALLSEGMENTSSBYLABEL_CMD]);
    StatusType res = GetAllSegmentsByLabel(DS, courseID, &images, &segments, &numOfLabels);

    free(images);
    free(segments);

    return error_free;
}

Solution

  • What happens if (*numOfSegments) == 0 is true in GetAllSegmentsByLabel?

    In that case you have still allocated 2 blocks of 0 bytes and they are lost because you set both pointers to nullptr before exiting the function in the if statement.

    Every malloc including malloc(0) must be freed.