cancel
Showing results for 
Search instead for 
Did you mean: 

stm32 hangs on malloc

gvandenbosch
Associate II
Posted on December 18, 2009 at 13:36

stm32 hangs on malloc

16 REPLIES 16
st3
Associate II
Posted on May 17, 2011 at 13:34

Quote:

The reason I want to use malloc is that I don't know how many I get, the other way around would be using a large array that can be filled with data but you will never use the whole array or if a mistake is made and the size of the array is too small the array will overflow.

But malloc cannot magically create RAM from nowhere, can it?

malloc can only allocate memory from the heap - so you have to define the heap to be big enough for the maximum number of elements that you'll require, don't you?

So, if you have to define the heap anyhow, you might just as well define a fixed array, mightn't you?!

remember that dynamic allocation adds an overhead and can also lead to problems with fragmentation, memory leaks, etc - which is why it is generally best avoided in embedded systems.

Quote:

in my opinion when there is a unknown amount of data to store malloc is used

Actually, malloc is most useful when the amount of memory available is unknown at build time - as is generally the case with PC-type applications.

When the amount of memory is known at build time - as is typical with embedded systems - you have to fix your heap size within that limit anyhow - so there is little advantage over a fixed array, but still several disadvantages.

st3
Associate II
Posted on May 17, 2011 at 13:34

Quote:

You might say that you can check the return value of malloc

It is (almost) certainly a failure to check the return value of malloc that is causing the OP's system to crash!

If you ever use malloc, you absolutely must check the return value from it!! :-o

Quote:

if you do you must test the application in ''worst case'' scenario

The trouble is, how do you determine what will cause the ''worst case''...?!

That's another trouble with malloc - it makes things non-deterministic...

st3
Associate II
Posted on May 17, 2011 at 13:34

Quote:

to be clear I never said you shouldn't check the return value of malloc.

Indeed you didn't.

Just emphasising to the OP that one really must always check the return value from malloc - as that is (almost) certainly the reason for his crash!

Quote:

this was not easy too define and yes using malloc makes testing (and especailly debugging) more difficult.

Indeed!

gvandenbosch
Associate II
Posted on May 17, 2011 at 13:34

You guys are right, I didn't looked from it in that perspective.

I think my problem is that I use malloc often in PC Applications (and Yes I check return values :-D), and with the same mindset I program for a microcontroller.

Thanks for making me clear that I shouldn't use malloc on a embedded system, I understand the risks now and will code with an array on a embedded platform instead of malloc structures from now on :-W

dannym
Associate II
Posted on July 27, 2012 at 20:32

Well I'm working through some ST-provided code which uses malloc() to create all its array variables, and uses about 2K of heap.  I'm not sure WHY it is written this way, the variables are used statically, only created in an initializer.  There's a deconstructor task to end them all, but I don't see what purpose this serves.

I am interested in the ''why'' here.  This code does have an RTOS option.  Is it so its usage can be loaded dynamically, like an app, and memory recovered later?

Well I spent considerable hair-pulling on this code before discovering the malloc() calls are failing because I didn't allocate 2K of heap.  And ST didn't provide any checking on the malloc() returns, so null pointers were creeping into the code.  

I am new to dynamic memory allocation in microcontrollers.  Now I have an interest in why they're needed (or if this is a universally bad idea), alongside a genuine hatred of them for all the trouble it just caused me (learning experience).  

Is it just me, or is it much more difficult to debug dynamically allocated variables?  I've got a struct with a 2D array inside.  Each row of the array is actually a pointer, and rows need not be in contiguous space.  But in doing so, I have a pointer to a structure with a pointer to an array of pointers to array rows.  I'm using Keil uVision, fairly new at this, and it seems like it's being very difficult to bring this up in a Watch window to determine if a pointer is NULL, or even just what data's in the array.  Correct me if I'm wrong, but uVision doesn't even know what dimensions the array IS, does it?  The size was set dynamically by malloc() at runtime, and I don't think uVision has any way to see or retain the size properties, making simple display of the array impossible.  I see Debug as important and so this is kind of a ''thing''.

My question, though, is this: in an STM32 microcontroller, what's the most practical way to write a CHECK for the malloc-failed condition?  Unless it has a screen, if you're not in Debug, there's not much it can do except stop dead.  There's no way to handle this and continue functioning.

Do we write a check for NULL onto every line that calls to malloc()?  Or use a passthrough malloc()-calling task that checks and has some sort of software-based exception handler if malloc() returns NULL?

Posted on July 27, 2012 at 21:04

One option is to fall over and die, a better solution is to have error propagation and unwind the current execution path to a point that can better handle or express the error. This might permit, for example, retrying and asking for a smaller allocation, or having a method that uses less or no dynamically allocated memory.

Some memory issues could be temporal, buffers might get freed up if output tasks are allowed to flush, etc.

The biggest problem with malloc/free in an embedded systems is that the available memory can be fragmented, you have enough to fill the request, but it's non-contiguous.

There are also a number of methods of expressing an error condition so you can better understand/resolve the issue. Storing a code to a file, a location in memory (RAM or FLASH), sending a message, or blinking an LED with different speeds and patterns.

Building a system that is impossible to diagnose or troubleshoot will usually result in your technical support staff dragging you into the parking lot and breaking your legs. That, or they'll make you speak to the customers who are screaming at them.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
dannym
Associate II
Posted on July 27, 2012 at 22:02

I'm sorry, but could you be more specific on your suggestion of ''error propagation and unwinding''? 

I did note that the code made a 2D array by asking for an array of pointers to rows, rather than a 2D array.  Thus the data isn't necessarily contiguous, which is easier to find in the heap, but even more prone to fragging, if you ever deconstruct them.  It seems unnecessary here though, because these arrays are like 3x3 or 7x7 of Float.  Finding 200 bytes of contiguous space shouldn't be a problem.

When you say ''retry''- I'm unclear on what you mean.  I could imagine an allocation task that initially tries to create a contiguous array, if that fails, then make an array with noncontiguous rows.  Although, if the code can handle noncontiguous rows, then allocation should have been coded that way to begin with, shouldn't it?  

How could ''retrying'' use a method that doesn't use dynamic allocation?  Because compile-time allocation already had to have happened, before dynamic runtime allocation.  I don't see how the allocation task could fallback to compile-time allocation.  The code-writer could be alerted to the problem and increase the heap- or rewrite it- which seems reasonable to me, I still don't quite understand the need to be using malloc() for everything- but if there's a way a dynamic allocation task could use ''a method that uses less or no dynamically allocated memory'', I'd like to learn about it.