ST7, not sure who your comments are aimed at but to be clear I never said you shouldn't check the return value of malloc. The reason I put worst case in quotes was to highlight that this was not easy too define and yes using malloc makes testing (and especailly debugging) more difficult.
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
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.
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?
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 (See Profile) Up vote any posts that you find helpful, it shows what's working..
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.