Hello, I have a small test program for mallo but it fail:
bool alloc(unsigned long int i){
Serial.printf("\r\n i = %lu\r\n", i);
Serial.printf("GetFreeHeap avant alloc: %lu\r\n",heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
static void *workBuff = heap_caps_malloc(i, MALLOC_CAP_8BIT);
if (workBuff != NULL){
Serial.printf("GetAllocHeap après malloc: %lu\r\n", heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
heap_caps_free(workBuff);
Serial.printf("GetFreeHeap après free: %lu\r\n", heap_caps_get_largest_free_block(MALLOC_CAP_8BIT));
return true;
}
Serial.println("Allocation non réussie!");
return false;
}
void setup() {
Serial.begin(115200);
while(!Serial){
;
}
Serial.println("Test begin");
}
void loop() {
unsigned long i = 1;
if (alloc(i)){
Serial.println("ok");
}
}
As you can see the loop call the method alloc with the number of byte to allocate.
After two loop the heap is corrupted after the free instruction.
Why ?
Hello chrisop,
I don't understand your reply.
In the alloc method i call malloc and free the alllocation.
Why did you see " You're trying to free the same allocation more than once which leads to heap corruption. Try removing static"
I disagree. workBuff gets set by a call to malloc. If non-null, it gets immediately freed. Next time around, the same repeats. I see no problem there.
But I am curious - How does OP KNOW the heap is getting corrupted? What is printed out. What happens when it "dies"? Keep in mind, some Serial output may be lost when it dies, unless you do a Serial.flush after each print.
The problem is that workBuff retains its value starting at the very first call to alloc. Its value never changes after it's set the first time. The important thing to note is that malloc is called only once. The memory is freed in alloc, and then the next time alloc is called, workBuff is already non-null, so it's freed again (which corrupts the heap because the memory is not allocated again).
What it retains (holds) is the pointer address, not the allocated buffer, may be the terminology was confusing. There is no notion of retain (count like in objective C) for this but yes the initialization only happens once hence the crash
It’s also a good practice to set a pointer to nullptr after freeing the data it pointed at.
Yes, that's what I meant. I used "retain" in the general meaning of the word (continue to have (something); keep possession of), rather than any specific meaning in another language. Thanks for the clarification.
I had to read your text twice as indeed for some reason I thought you were saying the free did not really free the memory as it was retained elsewhere.(which is a concept in some other languages for objects)