Using malloc and esp_get_free_heap_size()

zazas321
Posts: 231
Joined: Mon Feb 01, 2021 9:41 am

Using malloc and esp_get_free_heap_size()

Postby zazas321 » Thu Jul 20, 2023 7:44 am

Hello. I normally practice not using dynamic memory allocation, but I have a very simple question regarding creating buffer in heap memory:

See the example code below:

Code: Select all

/*
 * SPDX-FileCopyrightText: 2010-2022 Espressif Systems (Shanghai) CO LTD
 *
 * SPDX-License-Identifier: CC0-1.0
 */

#include <stdio.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_chip_info.h"
#include "esp_flash.h"

void app_main(void)
{
    printf("Hello world!\n");

    /* Print chip information */
    esp_chip_info_t chip_info;
    uint32_t flash_size;
    esp_chip_info(&chip_info);
    printf("This is %s chip with %d CPU core(s), WiFi%s%s, ",
           CONFIG_IDF_TARGET,
           chip_info.cores,
           (chip_info.features & CHIP_FEATURE_BT) ? "/BT" : "",
           (chip_info.features & CHIP_FEATURE_BLE) ? "/BLE" : "");

    unsigned major_rev = chip_info.revision / 100;
    unsigned minor_rev = chip_info.revision % 100;
    printf("silicon revision v%d.%d, ", major_rev, minor_rev);
    if(esp_flash_get_size(NULL, &flash_size) != ESP_OK) {
        printf("Get flash size failed");
        return;
    }

    printf("%" PRIu32 "MB %s flash\n", flash_size / (uint32_t)(1024 * 1024),
           (chip_info.features & CHIP_FEATURE_EMB_FLASH) ? "embedded" : "external");

    printf("Minimum free heap size: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());

    printf("esp_get_free_heap_size: %" PRIu32 " bytes\n", esp_get_free_heap_size());

  


    size_t size_to_allocate_1kb = 1000;
    uint8_t *ptr1;
    uint8_t *ptr2;


    ptr1 = malloc(size_to_allocate_1kb * sizeof(*ptr1));
    *(ptr1+5) = 555;
    printf("Minimum free heap size after allocating: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
    printf("esp_get_free_heap_size after allocating: %" PRIu32 " bytes\n", esp_get_free_heap_size());


    ptr2 = malloc(size_to_allocate_1kb * sizeof(*ptr2));
    printf("Minimum free heap size after allocating2: %" PRIu32 " bytes\n", esp_get_minimum_free_heap_size());
    printf("esp_get_free_heap_size after allocating2: %" PRIu32 " bytes\n", esp_get_free_heap_size());

}


The log:

Code: Select all

[1B][0;32mI (177) boot: Loaded app from partition at offset 0x10000[1B][0m
[1B][0;32mI (177) boot: Disabling RNG early entropy source...[1B][0m
[1B][0;32mI (189) cpu_start: Multicore app[1B][0m
[1B][0;32mI (189) cpu_start: Pro cpu up.[1B][0m
[1B][0;32mI (189) cpu_start: Starting app cpu, entry point is 0x40081048[1B][0m
[1B][0;32mI (0) cpu_start: App cpu up.[1B][0m
[1B][0;32mI (207) cpu_start: Pro cpu start user code[1B][0m
[1B][0;32mI (207) cpu_start: cpu freq: 160000000 Hz[1B][0m
[1B][0;32mI (207) cpu_start: Application information:[1B][0m
[1B][0;32mI (212) cpu_start: Project name:     hello_world[1B][0m
[1B][0;32mI (217) cpu_start: App version:      v5.0.3-dirty[1B][0m
[1B][0;32mI (223) cpu_start: Compile time:     Jul 19 2023 12:41:01[1B][0m
[1B][0;32mI (229) cpu_start: ELF file SHA256:  3cc860f1570c8e18...[1B][0m
[1B][0;32mI (235) cpu_start: ESP-IDF:          v5.0.3-dirty[1B][0m
[1B][0;32mI (240) cpu_start: Min chip rev:     v0.0[1B][0m
[1B][0;32mI (245) cpu_start: Max chip rev:     v3.99 [1B][0m
[1B][0;32mI (250) cpu_start: Chip rev:         v3.0[1B][0m
[1B][0;32mI (255) heap_init: Initializing. RAM available for dynamic allocation:[1B][0m
[1B][0;32mI (262) heap_init: At 3FFAE6E0 len 00001920 (6 KiB): DRAM[1B][0m
[1B][0;32mI (268) heap_init: At 3FFB2770 len 0002D890 (182 KiB): DRAM[1B][0m
[1B][0;32mI (274) heap_init: At 3FFE0440 len 00003AE0 (14 KiB): D/IRAM[1B][0m
[1B][0;32mI (280) heap_init: At 3FFE4350 len 0001BCB0 (111 KiB): D/IRAM[1B][0m
[1B][0;32mI (287) heap_init: At 4008BA0C len 000145F4 (81 KiB): IRAM[1B][0m
[1B][0;32mI (294) spi_flash: detected chip: generic[1B][0m
[1B][0;32mI (298) spi_flash: flash io: dio[1B][0m
[1B][0;32mI (303) cpu_start: Starting scheduler on PRO CPU.[1B][0m
[1B][0;32mI (0) cpu_start: Starting scheduler on APP CPU.[1B][0m
Hello world!
This is esp32 chip with 2 CPU core(s), WiFi/BT/BLE, silicon revision v3.0, 4MB external flash
Minimum free heap size: 301716 bytes
esp_get_free_heap_size: 301716 bytes
Minimum free heap size after allocating: 300712 bytes
esp_get_free_heap_size after allocating: 300712 bytes
Minimum free heap size after allocating2: 300712 bytes
esp_get_free_heap_size after allocating2: 300712 bytes

As you can see from the code, I allocate 2 1kB chunks in heap memory using:

Code: Select all

    ptr1 = malloc(size_to_allocate_1kb * sizeof(*ptr1));
and

Code: Select all

    ptr2 = malloc(size_to_allocate_1kb * sizeof(*ptr2));

I am also monitoring the remaining heap size using:

Code: Select all

esp_get_free_heap_size
and I have noticed that if I allocate bunch of memory in heap but do not use it (do not assign any value to it), it is not going to occupy and space.

but if I do:

Code: Select all

    *(ptr1+5) = 555;
then 1kB of space will be occupied.

From the logs, you can see that after I declare ptr1, the memory is reserved from the heap, but after I declare ptr2 it is not reserved. See logs:

Code: Select all

Minimum free heap size: 301716 bytes
esp_get_free_heap_size: 301716 bytes
Minimum free heap size after allocating: 300712 bytes
esp_get_free_heap_size after allocating: 300712 bytes
Minimum free heap size after allocating2: 300712 bytes
esp_get_free_heap_size after allocating2: 300712 bytes
As you can see from above, after allocating ptr1, heap size decreased from 301716 to 300712. But after allocating ptr2, remaining heap memory hasnt changed



Can someone help me understand whether that is expected behaviour?

ESP_Sprite
Posts: 9730
Joined: Thu Nov 26, 2015 4:08 am

Re: Using malloc and esp_get_free_heap_size()

Postby ESP_Sprite » Thu Jul 20, 2023 9:38 am

Decently sure it's the compiler being smart enough to see that the memory is never used and as such doesn't need to be actually allocated, so it probably removes the references to malloc() while compiling.

Edit: Seems the compiler can do that, see here; note that the two malloc() lines don't have any output in the assembly window. I'm not sure why for you the used variable does actually force the compiler to compile in malloc(), that may be a compiler setting that's a bit different.

Who is online

Users browsing this forum: No registered users and 120 guests