Page 1 of 1

Corrupt heap with ESP32

Posted: Fri Sep 23, 2022 9:40 pm
by Slev1n
Hello, I am having a little platformIO project with the ESP32 using VScode as IDE and arduino as framework using C++. I am currently struggling with a CORRUPT HEAP error. Here the error message:
CORRUPT HEAP: Bad head at 0x3ffbb0f0. Expected 0xabba1234 got 0x3ffb9a34
assert failed: multi_heap_free multi_heap_poisoning.c:253 (head != NULL)
Backtrace:0x40083881:0x3ffb25400x4008e7e5:0x3ffb2560 0x40093d55:0x3ffb2580 0x4009399b:0x3ffb26b0 0x40083d41:0x3ffb26d0
0x40093d85:0x3ffb26f0 0x4014e3f5:0x3ffb2710 0x400d2dc6:0x3ffb2730 0x400d31e3:0x3ffb2750 0x400d9b02:0x3ffb2820
The good thing is I think I have tracked down the origin:
Start -> the device initialises some stuff -> goes to sleep -> wakes up -> measures 5 sensor values and stores them in a Datacontainer -> writes data from container to file (SD card) -> clears the Datacontainer, this last step causes CORRUPT HEAP.
I was trying to track down the problem using

Code: Select all

heap_caps_check_integrity_all(true)
it returns true until the datacontainer memory is released by the "delete" operation. But I made one observation, resetting the datacontainer only causes the CORRUPT HEAP error when my function

Code: Select all

write_data_container_to_file(SD, data_file_path.c_str(), data, RTC_timestamp)
is executed right before. EVEN when the whole code inside the function is commented, the error is triggered. When I comment the function call, no error is happening.

Here is some more information about the datacontainer class I am talking about (I have attached the whole class header file):

Code: Select all

template <typename Elementtype>
class DataContainer
{
private:
    Elementtype **datalist;
    int maxsize;
    std::size_t currentsize; // How much data is saved in datalist

public:
    DataContainer(int maxcapacity);
    ~DataContainer();

    void init_data_saving();
    void add_data(Elementtype &new_Element, const int typenmbr);
    void end_data_saving();

    Elementtype *operator[](int posnumber) const;
    const std::size_t get_currentsize() const;

    Elementtype **get_all_data() const;
    void reset_all_data();
};
I have to confess, that I am quite new to C++ and I have taken over this DataContainer structure from someone else without further instructions - so I do not understand everything about it.
This public method finally causes the error:

Code: Select all

/* Deletes all Data of Datacontainer and allocates new memory*/
template <typename Elementtype>
void DataContainer<Elementtype>::reset_all_data()
{
    for (int i = 0; i < currentsize; i++)
    {
        if (datalist[i])
            Serial.println(heap_caps_check_integrity_all(true));
            delete datalist[i]; <-- Triggers the Error
            Serial.println(heap_caps_check_integrity_all(true));
    }
    delete datalist;

    datalist = new Elementtype *[maxsize];
    for (int i = 0; i < maxsize; i++) // Declare a memory block of size maxsize
    {
        datalist[i] = new Elementtype[SPIRU_SENSOR];
    }

    currentsize = 0;
}
I have also tried getting some information about the heap right before calling the datacontainer reset using

Code: Select all

heap_caps_print_heap_info(MALLOC_CAP_DEFAULT);
Here is the output:
Heap summary for capabilities 0x00001000:
At 0x3ffb8000 len 6688 free 168 allocated 3888 min_free 168
largest_free_block 0 alloc_blocks 39 free_blocks 1 total_blocks 40
At 0x3ffb0000 len 25480 free 14928 allocated 8304 min_free 10956
largest_free_block 14836 alloc_blocks 7 free_blocks 1 total_blocks 8
At 0x3ffae6e0 len 6192 free 3980 allocated 36 min_free 3980
largest_free_block 3956 alloc_blocks 1 free_blocks 1 total_blocks 2
At 0x3ffb6388 len 7288 free 180 allocated 4488 min_free 172
largest_free_block 0 alloc_blocks 38 free_blocks 2 total_blocks 40
At 0x3ffb9a20 len 16648 free 4768 allocated 9260 min_free 148
largest_free_block 4596 alloc_blocks 38 free_blocks 1 total_blocks 39
At 0x3ffc81a8 len 97880 free 64236 allocated 31204 min_free 64236
largest_free_block 63476 alloc_blocks 23 free_blocks 2 total_blocks 25
At 0x3ffe0440 len 15072 free 12908 allocated 0 min_free 12908
largest_free_block 12788 alloc_blocks 0 free_blocks 1 total_blocks 1
At 0x3ffe4350 len 113840 free 111676 allocated 0 min_free 111676
largest_free_block 110580 alloc_blocks 0 free_blocks 1 total_blocks 1
Totals:
free 212844 allocated 57180 min_free 204244 largest_free_block 110580
So at this point I am quite lost and have no idea where the error comes from. If there is any suggestion it is more than welcome!

Re: Corrupt heap with ESP32

Posted: Sat Sep 24, 2022 5:21 pm
by mbratch
I haven't examined everything you posted in detail, but you did mention this:

Code: Select all

delete datalist[i];
If this is really the case, then either `i` is out of range for the `datalist`, or `datalist[ i ]` contains an address that was already deleted or not allocated. So look around for what might cause those situations.

Re: Corrupt heap with ESP32

Posted: Sun Sep 25, 2022 8:06 am
by Slev1n
Thank you for the response. So far I have rewritten my DataContainer class. The container is now not pointing to an array of pointers, which point to different arrays to get a 2D array, but simply pointing to a 1D array with the same size. Makes indexing a little bit more "complex" but it is faster and easier to

Code: Select all

delete
.

For example, I do not have to care about the index in

Code: Select all

delete[index]
. However, the error still occurs at the same "time" when I release the memory again. I have already shifted my "problematic" code to the beginning of my main.cpp still showing the same behavior. But I will do as you suggested.

One more thing, which I still do not no how to interpet. Why is the HEAP CORRUPTION only triggered by the

Code: Select all

delete
, when I call the function

Code: Select all

write_data_container_to_file(fs::FS &fs, const char *path, DataContainer<uint16_t> data, const char *RTC_timestamp)
, even when this function is empty (I commented out all lines)? When I comment out the function call, the HEAP CORRUPTION is not triggered but a little later I get
heap != NULL && "free() target pointer is outside heap areas
So yeah, somehow I am messing up allocating and relaeasing the memory. Maybe you could check my class I have attached TO THIS POST (not the first post), maybe I am overseeing something. Thanks in advance.

Re: Corrupt heap with ESP32

Posted: Mon Sep 26, 2022 7:16 am
by Slev1n
I have finally found the, rather obvious, reason for the HEAP CORRUPTION. The code I am using has not been entirely written by me but lately I have taken over this project again, hence I did not double check all the new input closely enough and there was an allocation/deallocation call close by from another function. It was allocating an array of chars

Code: Select all

char* array = new char[50]
but deallocated only

Code: Select all

delete array
but

Code: Select all

delete[] array
would have been correct. Well, removing this part led to a working code execution. Thanks for the support.

EDIT: How can I mark a post as solution?

Re: Corrupt heap with ESP32

Posted: Tue Sep 27, 2022 2:02 am
by chegewara
I see you solved the problem but i will answer anyway.

Code: Select all

delete datalist[0];
delete datalist; // <---- this will lead to heap corrupt, because datalist == datalist[0]
This code is also incorrect (missing parenthesis):

Code: Select all

      if (datalist[i])
            Serial.println(heap_caps_check_integrity_all(true));
            delete datalist[i]; 					<-- Triggers the Error, when its NULL
            Serial.println(heap_caps_check_integrity_all(true));