Corrupt heap with ESP32

Slev1n
Posts: 4
Joined: Wed Nov 01, 2017 3:49 pm

Corrupt heap with ESP32

Postby Slev1n » Fri Sep 23, 2022 9:40 pm

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!
Attachments
DataContainer.h
(4.21 KiB) Downloaded 225 times

User avatar
mbratch
Posts: 303
Joined: Fri Jun 11, 2021 1:51 pm

Re: Corrupt heap with ESP32

Postby mbratch » Sat Sep 24, 2022 5:21 pm

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.

Slev1n
Posts: 4
Joined: Wed Nov 01, 2017 3:49 pm

Re: Corrupt heap with ESP32

Postby Slev1n » Sun Sep 25, 2022 8:06 am

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.
Attachments
DataContainer.h
(4.28 KiB) Downloaded 203 times

Slev1n
Posts: 4
Joined: Wed Nov 01, 2017 3:49 pm

Re: Corrupt heap with ESP32

Postby Slev1n » Mon Sep 26, 2022 7:16 am

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?

chegewara
Posts: 2376
Joined: Wed Jun 14, 2017 9:00 pm

Re: Corrupt heap with ESP32

Postby chegewara » Tue Sep 27, 2022 2:02 am

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));

Who is online

Users browsing this forum: No registered users and 112 guests