Author Topic: malloc() returns NULL  (Read 1536 times)

0 Members and 1 Guest are viewing this topic.

Offline awergh

  • CPC6128
  • ****
  • Posts: 266
  • Country: au
  • Liked: 129
  • Likes Given: 262
malloc() returns NULL
« on: 13:58, 22 June 16 »
Using malloc() might be a mistake but as you learn more from making mistakes I prefer to think of it as a learning opportunity  :P .


So I've been playing with CPCTelera lately and decided to make use of malloc but it appears to always return NULL.
My understanding is that SDCC allocates 1KB for the heap and surely there should be memory available for me to use.

Is there something I'm doing wrong or not allowed to do? Or do I have to write and manage my own heap for even more learning opportunities :P . (Not that understanding how malloc and free work would be a bad thing anyway)


Code: [Select]
if(malloc)
{   
printf("malloc succeeded");
}
else
{   
printf("malloc returned NULL");
}
« Last Edit: 14:00, 22 June 16 by awergh »

Offline ronaldo

  • Dev
  • 6128 Plus
  • *****
  • Posts: 627
  • Country: es
    • Fremos Blog
  • Liked: 895
  • Likes Given: 808
Re: malloc() returns NULL
« Reply #1 on: 15:17, 22 June 16 »
You can use malloc, but it not recommended in general. It is normally much preferable to do manual memory management.

Anyways, the problem when you use malloc with a standard CPCtelera project is that the compiler is told not to use _GSINIT area. That means that global variables are not initialized the way SDCC does (remember that SDCC is designed to generate ROM binaries, which damages size and performance on initialization in RAM executables). Therefore, the variable ___sdcc_heap_free is not initialized (it defaults to 0). Therefore, you get a 0 in return to your call to malloc, due to malloc thinking that heap starts at 0.

However, there is an easy solution for that:
Code: [Select]
#include <cpctelera.h>
#include <stdio.h>
#include <stdlib.h>

// Need to be declared as it is an internal function that is not exported by the header file
void __sdcc_heap_init();

void main(void) {
   u8 *mem;

   __sdcc_heap_init();      // Initialize HEAP (1023 bytes by default)
   mem = (u8*)malloc(10);   // Reserve 10 bytes

   // Check Malloc
   if (mem == NULL) {
      printf("Malloc returned NULL!\n\r");
   } else {
      u8 i;
      printf("Malloc returned %x\n\r", mem);

      // Store something as test   
      for (i=0; i < 10; i++)
         mem[i] = 2*i;
      for (i=0; i < 10; i++)
         printf ("%d ", mem[i]);
   }

   // Loop forever
   while (1);
}
After compilation, you may check obj/yourproject.map file and you will see the s__HEAP area created, with the symbols ___sdcc_heap_free, ___sdcc_heap and ___sdcc_heap_end. By looking at their memory addresses, you will know where they are and their size. If you want to play around with them, you need to create your own heap.s file with this symbols and compile it with your project. You will find original heap.s at cpctelera/tools/sdcc-3.5.5/src/device/lib/z80/heap.s.
« Last Edit: 15:19, 22 June 16 by ronaldo »