Assertion Failure upon freeing heap memory

alubee
Posts: 5
Joined: Tue Nov 28, 2023 3:01 pm

Assertion Failure upon freeing heap memory

Postby alubee » Thu Mar 07, 2024 7:59 pm

Hello,

I am having a headache dealing with a memory leak that I have been having.
Although, once I discovered which resource I remained to be freeing, I receive, at times, this assertion error
assert failed: block_next tlsf_block_functions.h:94 (!block_is_last(block))
. Given I cannot find any resources on this error, I hope that someone in here can help me out.

Context
Dependencies:
  • ESP-IDF v5.1.2
  • ESP32C3
I have created two functions to allocate- and free a struct, all of which are given below (granted, this in not the most elegant solution). In my logic, I have two instances (x and y) of the "my_struct_t" for different types of data. Once I obtain either of the types of data as a byte array, my logic allocates space for it on the heap, and stores the pointer in the corresponding struct instance and updates the metadata.

At some point, I will release the struct resources, and I then call the freeing function below, where the assertion error will happen in two places. It happens if the number of byte arrays added to x is 0, and is freed, the assertion error happens (the the trigger line below). This will not happen if the same is the case for instance y[/list]. This issue happens only in line A, if line B is removed.

I have checked the following:
  • Check whether it is heap corruption, both by using the "esp_heap_caps" library, or by allocating some random memory and freeing it right before the lines A and B. This does not change the result
  • There are no concurrent processes that could be corrupting- or freeing the memory
  • The are seemingly no buffer overflows or any sort of memory corruption
  • The processing of the byte arrays for the instances x and y are identical
My questions
  • What does this assertion error signify/indicate? What I have been able to deduce is quite limited
  • Do I have some erroneous way of handling allocating- and freeing the resources?
  • Or could this be an issue in the tlsf implementation?
Hope someone can help me.
Thanks in advance!

Code

Code: Select all

typedef struct {
    size_t count;
    uint8_t **data;
    size_t *lengths;
} my_struct_t;

Code: Select all

my_struct_t *my_struct_malloc(const size_t max_num)
{
    my_struct_t *my_s = (my_struct_t *)malloc(sizeof(my_struct_t));
    if (!my_s) {
        return NULL;
    }
    my_s->data = (uint8_t **)malloc(max_num * sizeof(uint8_t *));
    if (!my_s->data) {
        free(my_s);
        return NULL;
    }

    my_s->lengths = (size_t*)malloc(max_num * sizeof(size_t));
    if (!my_s->lengths) {
        for (size_t i = 0; i < max_num; i++) {
            free(my_s->data[i]);
        }
        free(my_s->data);
        free(my_s);
        return NULL;
    }
    my_s->count = 0;

    return my_s;
}

void my_struct_free(my_struct_t *my_s)
{
    for (int i = 0; i < my_s->count; i++) {
        if (my_s->data[i]) {
            free(my_s->data[i]);
            my_s->data[i] = NULL;
        }
    }

    if (my_s->data) {
        free(my_s->data); // <- Line A assertion error trigger
        my_s->data = NULL;
    }
    if (my_s->lengths) {
        free(my_s->lengths);
        my_s->lengths = NULL;
    }
    my_s->count = 0;
    
    free(my_s); // <- Line B assertion error trigger
}

MicroController
Posts: 1216
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Assertion Failure upon freeing heap memory

Postby MicroController » Fri Mar 08, 2024 8:25 am

Note that malloc does not clear/zero the allocated memory.
Hence in your code

Code: Select all

free(my_s->data[i]);
may try to free some 'random' pointer(s), because data[ i ] is never initialized.
This could cause heap corruption which can yield assertion failures in heap management code like the one you got.

alubee
Posts: 5
Joined: Tue Nov 28, 2023 3:01 pm

Re: Assertion Failure upon freeing heap memory

Postby alubee » Wed Mar 13, 2024 8:38 am

Hi

Memory blocks associated to the pointer in

Code: Select all

my_s->data[i]
is initialized elsewhere, because the payloads that the array elements point to can become rather large. But the count should reflect how many data-elements are initialized.

But I will double check the contents of the data elements to be sure.

alubee
Posts: 5
Joined: Tue Nov 28, 2023 3:01 pm

Re: Assertion Failure upon freeing heap memory

Postby alubee » Wed Mar 13, 2024 9:19 am

Checking the contents of

Code: Select all

data[i]
before freeing the block in my_struct_free, there is always initialized data inside.

MicroController
Posts: 1216
Joined: Mon Oct 17, 2022 7:38 pm
Location: Europe, Germany

Re: Assertion Failure upon freeing heap memory

Postby MicroController » Wed Mar 13, 2024 1:30 pm

Careful :)

Code: Select all

    my_s->lengths = (size_t*)malloc(max_num * sizeof(size_t));
    if (!my_s->lengths) {
        for (size_t i = 0; i < max_num; i++) {
            free(my_s->data[i]);
        }

Who is online

Users browsing this forum: Google [Bot] and 112 guests