cancel
Showing results for 
Search instead for 
Did you mean: 

When is going malloc() / dynamic allocation to be fixed?

DavidAlfa
Senior II

Edit: It seems there's a bug that will randomly delete sysmem.c and syscalls.c.

If it happens, cubeMX won't regenerate them.

Also no warnings at compile time, so you won't suspect anything was deleted.

So the solution is to make a new empty project and copy these files back.

___________________________________________________________________________________ 

I don't know if it's a bug, wrong initialization, or lacking code.

I remember once in 2019 where it worked, I could run malloc(X) and the pointer would be null ​if wanting too much.

But since then, none of the Cube IDE versions have worked correctly.

I can run a 100KB malloc on a ​16KB stm32, yet it will return a valid pointer.

Of course a hard fault will happen when you try to access the memory.

I had to modify​ every project to use static allocation, which is sometimes a problem because I could save a lot of RAM when certain parts of the code is not being used.​

The minimum heap allocation​ just reserves the heap at compile time, doesn't fix anything.

Also, free() doesn't seem to work correctly.​

I can malloc 64KB on a 128KB device and use it.

But if I malloc 1KB and 16KB, then free both, I can't malloc 64KB (it does, but outside the memory limits).

I don't understand why, as these pointers where freed up,​ so memory fragmentation shouldn't be happening?​

I'm spending​ more time in looking over these bugs than on my own ones...

Don't tell me​ that I have to increase heap. Because I could put 16TB of heap, and still get hard faults when it goes too far.

Why doesn't malloc check the remaining space?

14 REPLIES 14

> At some point, sysmem.c and syscalls.c dissapeared. I'm still trying to find the culprit.

Interesting...

Use version control for your projects. It will notice any missing files.

> But the thing is that without these files, it compiles ok, without any warning.

The default library likely has an empty _sbrk routine that does nothing.

DavidAlfa
Senior II

Yeah, I usually do. Probably these files were gone from the very beginning (before pushing Head for the first time) , and since I never used dynamic allocation in this project... never noticed.

Now, I made a few new projects. Sometimes the files are gone, sometimes not.

Didn't find the way to always reproduce the problem, it's very random.

The problem now is that it seems I'm having internal fragmentation. Not external. Let me explain:

From malloc.h:

struct mallinfo {
  size_t arena;    /* total space allocated from system */
  size_t ordblks;  /* number of non-inuse chunks */
  size_t smblks;   /* unused -- always zero */
  size_t hblks;    /* number of mmapped regions */
  size_t hblkhd;   /* total space in mmapped regions */
  size_t usmblks;  /* unused -- always zero */
  size_t fsmblks;  /* unused -- always zero */
  size_t uordblks; /* total allocated space */
  size_t fordblks; /* total non-inuse space */
  size_t keepcost; /* top-most, releasable (via malloc_trim) space */
};

 Test:

#include <malloc.h>
 
struct mallinfo info;		// To gather current mem info
uint8_t *a, *b, *c, *d;		// Test ptr
 
a = malloc(8192);		// Allocate 8KB
b = malloc(1024);		// Allocate 1KB
c = malloc(810);		// Allocate 810B
d = malloc(1492); 		// Allocate 1492B
info = mallinfo();		// arena=11552 , uordblks=11552
free(a);
free(b);
free(c);
free(d);
info = mallinfo();		// arena=11552, fordblks=11552
 
a = malloc(10240);    		// Allocate 12KB
info = mallinfo();		// arena=23848, uordblks=12296, fordblks=11552
free(a);
info = mallinfo();		// arena=23848, fordblks=23848

After freeing up all the memory, it will not reuse it if the next allocation is bigger than the total previous.

So it gets fragmented anyway, although the heap is completely free.

After few runs the heap will fail.

After 1st malloc: 
Heap: [8192][1024][810][1492] (11552 due alignment, usage variables)
       (a)   (b)   (c)   (d)
 
After free:
Heap: [11552]
      (free)
 
Then, when allocating 12KB, this happens;
Heap: [11552] [12296]
      (free)  (new alloc)
 
Instead:
Heap:  [12296]
       (new alloc)

If the free region is smaller, it works:

a = malloc(106736);
  info = mallinfo();    // Total used = 106744
  free(a);
  a = malloc(100000);    // Works

But if you request only 1 byte more, it try to allocate at the end of the free space, and fail:

a = malloc(106736);
  info = mallinfo();    // Total used = 106744
  free(a);
  a = malloc(106745);    // Doesn't work

A fix is to first allocate all the heap:

a = malloc(121*1024);    // Allocate 121KB (Max heap)
free(a);
// Now any allocation will work and not cause any fragmentation when freed up

Looks nice. Will try it. Thanks!

With the first huge allocation fix, it seems to work correctly now.

If I get any issues, I'll definitely check that manager 👍

I'm trying to make a multi format music player (Wav, MP3, Flac, Opus...), so, depending on the file, the correct decoder is allocated.

The issue was that ex. the MP3 decoder would get after the empty space of the WAV buffer, instead starting at "0", and after few files the heap would crash.

Now it doing fine! (Still fighting top run the flac and opus decoders :weary_face: )