How to use ps_malloc/malloc with PSRAM on ESP32?

I read a few posts here on this subject, but I must be missing a crucial setting. Here is my script:

#include <Arduino.h>
#include <Streaming.h>

using namespace std;

constexpr int s = 1'000'000;

void setup() {
  Serial.begin(115200);
  delay(1000);
  Serial << "Chip model: " << ESP.getChipModel() << ", " << ESP.getCpuFreqMHz() << "MHZ, " << ESP.getChipCores() << " cores\n";
  Serial << "Free heap: " << ESP.getFreeHeap() << "/" << ESP.getHeapSize() << " " << ESP.getMaxAllocHeap() << " max block\n";
  Serial << "Free PSRAM: " << ESP.getFreePsram() << "/" << ESP.getPsramSize() << " " << ESP.getMaxAllocPsram() << " max block\n";
  Serial.flush();
}

void loop() {
  // auto a = (int16_t*)ps_malloc(s);
  auto a = (int16_t*)malloc(s);

  for (int i = 0; i < s; i++)
    a[i] = i%4242;
  
  Serial << a[4241] << endl;
  free(a);
  delay(1000);
}

and platformio.ini:

[env:esp32cam]
platform = espressif32
board = esp32cam
framework = arduino
monitor_speed = 115200
monitor_rts = 0
monitor_dtr = 0
lib_deps = 
	mikalhart/Streaming@^1.0.0
build_unflags = -std=gnu++11
build_flags = 
  -std=gnu++2a
  -DBOARD_HAS_PSRAM
  -DCONFIG_SPIRAM_USE_MALLOC
  -mfix-esp32-psram-cache-issue  

I’m getting this output with both malloc and ps_malloc:

Chip model: ESP32-D0WDQ5, 240MHZ, 2 cores
Free heap: 340424/365484 118772 max block
Free PSRAM: 4192139/4192139 4128756 max block
4241
CORRUPT HEAP: Bad tail at 0x3f8f4ab4. Expected 0xbaad5678 got 0x0e670e66

assert failed: multi_heap_free multi_heap_poisoning.c:253 (head != NULL)

Any ideas how to fix it? BTW, the same error happens with s = 100'000.

No. Malloc takes the number of bytes to allocate. You give it 1 million there. So you’ll have one million bytes. You cast a to be int16_t pointer. An int16_t is two bytes (16 bit is 2 bytes). You then create a for loop in which you want to write 1 million int16_t elements. But the 1 million bytes you allocated are only worth half a million int16_ts. Thus you’re writing out of bounds with respect of the allocated memory, overwriting heap housekeeping / tracking data, which is detected and your program is terminated.

If you want to allocate n number of elements of a certain type t, you would to malloc( n * sizeof(t));, so e.g., malloc(1000000 * sizeof(int16_t)); to get a memory buffer that can hold 1 million int16_ts.

1 Like

Ooops! You are right. I started with uint8_t and forgot to edit malloc when changed to int16_t. Thanks.