Dynamic Memory Allocation in Embedded Apps?
shootTheMessenger asks: "My company is porting our C++ Windows app to C in an embedded device and the question of whether to use dynamic memory allocation continues to come up. So far I have resisted malloc/free use but it gets tedious having the same argument with the next set of managers to take an interest in the project. Is there a definitive answer on the subject, especially one to counter the 'we have plenty of RAM - 16MB - so why not use dynamic allocation' argument? A quick google search finds that some sites frown on allocations within embedded applications, while others say it is OK in some contexts and yet others hack around it with pseudo-static allocations. How do you feel about this particular subject?"
Over to comp.arch.embedded
Lots of seasoned pros that can give you a good answer.
"Eve of Destruction", it's not just for old hippies anymore...
If you have dynamic memory allocation, some day you're going to run out. If you're prepared to handle that case, either by (a) crashing or (b) recovering, then doing dynamic memory allocation will save you a good amount of development effort for a cost you've already decided to pay. If you're not going to allow (a), the question is whether (b) is more or less effort than just doing static allocation. That depends heavily on exactly what you're doing... but 16MB of memory is gargantuan, for many things.
I've had this sig for three days.
My company is porting our C++ Windows app to C in an embedded device and the question of whether to use dynamic memory allocation continues to come up.
OK, I realise I know precious little about embedded devices, but exactly why do you even need to port the code from C++ to C. Surely there's a C++ compiler for the device, but if there isn't, naturally I see the issue.
Secondly, dynamic memory in an embedded device?! Something seems awry here. Would preallocating memory work just as well? You, in theory, know all the parameters and tolerences beforehand.
Lastly, going back to the first paragraph, I'd keep away from C if I could, especially considering that the C++ system is likely object oriented. On top of that new/delete is much superior to the malloc/free. But that is just my humble C++ centric opinion!
May the Maths Be with you!
No one here can answer it without more information. Whats the target platform, Linux, WinCE, QNX? What type of data needs to be accessed? Whats the storage media, DOC, compact flash, hard disk?
You really can't expect to receive a practical answer without giving us more information.
Enjoy,
It's just the normal noises in here.
We need a new moderation category:
Grumpy
Trouble is, I can't decide if it should be +1 or -1.
Yeah, I always love it when a person comes to a public forum, being purposely vague for whatever reason and asks a question that really depends on the unmentioned.
For example, if your embedded device runs embedded Windows, I don't really see the problem. On the other hand, a Windows GUI app really can't be ported to the vast majority of embedded devices out there.
Speaking of embedded Windows, the subsystem is going to affect whatever it is you write.
Given that you are talking about a "next set of managers", I figure it isn't really a flying leap to consider the possibility that you don't really have a specific embedded device in mind, or perhaps your people have looked at a WinCE device and said "Hey these things pretty much come with 16MB standard nowadays, wouldn't it be cool if we could get our application onto one of these babies!"
The fact is that your app isn't going to be occupying that device alone, so look at how the rest of the programming treats the device.
I'm bored now, so bye!
Do you know exactly how much memory you need? If so, allocate it statically.
If you don't, there's no good way to avoid dynamic allocation. The best you can do is allocate a certain amount statically and try to get by with that. If you need more, you have to throw an error. If you need less, you're a memory hog - not a good thing in an embedded program.
Dynamic memory management isn't so scary in C++. If you absolutely have to use C, God be with you.
It's fine to malloc/free in 16M, just keep a grasp on the situation.
* install a malloc debug library on all test boxes to find all unfreed, double freed, or overwritten chunks. don't ship until all mem is accounted for.
* don't allow, or at least discourage, "little" mallocs like strdup() or allocation of singleton structs.
* do something sensible when malloc starts returning NULL. don't just seg fault or abort.
* destruction test: malloc 15.5MB (and incr until failure) of space at the start just to establish the limit, then back it down 50K and see how long your embedded app can live in that space and watch how it dies. as you fix things, expect it to die in different places each time.
* nm (or elfdump these days) your c lib and look for library functions that link to malloc or calloc. if your embedded OS ships with source, you can just grep for it.
* if your app has a log file, put a printf(sbrk(0)) in every few minutes (or less as appropriate) so you can watch for unexpected growth over time and spikes related to usage.
just some ideas.
Memory allocation is a black art, and fiddling with it is best left up to the wizards.
That said, the first article linked to gives some good recommendations on memory allocation. But I would go one step further and say that coding the app using malloc then analyzing the behavior is your best bet.
For example, code the application using just malloc but tag each block of memory with an identifier so you can figure out where the memory was allocated from. Next, wrap the malloc/free calls with timing code that samples at fixed intervals to evaluate the overall performance of the allocator. After running the app for a representative interval, break in with the debugger and check your stats. If malloc is taking a long time or if the heap is fragmented, determine your most commonly allocated items and see about making an allocator specifically for them.
Fragmented heaps are a bad thing, so if I'm going to be allocating lots of objects of the same size I usually write a custom block allocator for them with a free block list. Makes allocation fast and keeps the fragmentation low.
I never personally saw it fragment to the point of failure, but another engineer said he had had to debug that situation on this system- a particular sequence of allocation did this once (in many years).
This problem was solved by using a different memory allocator. That was a rare problem on a huge, long lived project.
Overall, I shouldn't sweat it too much, fragmentation causing the memory allocator to fail is rare enough and there are things you can do to solve the problem if it does occur. But you'll need a guru to solve it if it does happen.
-WolfWithoutAClause
"Gravity is only a theory, not a fact!"Memory fragmentation is murder on embedded devices. Do your best to avoid dynamic allocation unless static pools results in huge memory waste because your app is highly modal. Where dynamic allocation is a must, set up multiple heaps and find points where you can add code to free everything on that heap when switching modes to guarantee a fresh slate. If you have tons of small allocations, also consider setting up special heaps that handle fixed-size allocations. Having these parcelled off into their own area can go a long way toward fragmenting the space where the bigger allocations reside and you might find it's easier to find points where you can wipe heaps without the small allocations in the way.
Why would you do that? There's nothing about C++ that rules it out on embedded devices. I smell a bad vendor toolchain. Rule no.1 for sane embedded device development: USE THE GNU TOOLCHAIN. Then you can use C++ and half your porting task is gone. You can use the same toolchain with an x86 target for testing on PCs. You wouldn't happen to be using Green Hills, or god forbid Tasking would you?
So far I have resisted malloc/free use but it gets tedious having the same argument with the next set of managers to take an interest in the project.
Removing dynamic memory management is a noble goal but it goes deep into your coding style, to the extent that you basically end up with forked code instead of portable code - one version for each target inside big #ifs. One nice alternative I've used in the past is a stack separate from the call stack. You can either allocate a fixed size stack using malloc (say, 4MB for a task), or from a fixed location such as on-chip RAM. Allocations are stricly last-alloc'd-first-free'd, which actually fits most usage patterns. The key advantage is you can throw away the entire pool in a single call (pop all), for example when an error occurs, or if you run out of memory. This makes error handling much, much simpler than having a ton of delete's depending on how far you got. It also makes allocation overhead extremely small - it's basically just pointer arithmetic. It's just a souped up "alloca", where the stack isn't the function call stack, so it doesn't go away when the function does.
Best of all, if you use this method you can have a non-embedded version of the "stack" allocator which just uses malloc instead. I've got an example app which does no dynamic memory allocation linked from my profile (it's a Vorbis decoder).
Ahh yes, everyone comments with strong opinions without stating important assumptions. The simple answer is "yes, of course you can dynamically alloc memory". The important question not revealed is "why?". Once you have figured out exactly what the memory-related requirements are for you application then you can determine if you need dynamic allocations.
To answer that you need to ask questions like:
Will the app be long-running? If yes, you probably don't want a scheme that will fragment memory because eventually your heap will be too fragmented to allocated necessary contiguous blocks and it will have to reset.
Does the app need to allocate quickly? If yes, then you'll want to avoid allocating at all. Size your buffers ahead of time and never allocate dynamically. Also note that this is not to be confused by with hard real-time requirements. Many real-time applications need only bounded time on operations, so an ordinary allocator would perform very well on average and have known maximums because of bounded initial heap size.
Do you have to supply your own dynamic allocator? If there is an allocator available on the system, that may be the best route.
What are the patterns of your allocations? Does the app allocate many small chunks, a mixture of small and large; are they long lived or short lived? Allocation sizes effect performance and size usage of dynamic allocators.
I'll stop know because I can't think of any other good reasons off-hand. Static allocation is the best thing for many reasons - easy to use, easy to analyze, very fast. That's not practical for all applications, so my advice is to go with a simple allocator next - for C, malloc is good because everyone should know how to use it. Don't worry about speed or efficiency too much - performance usually isn't a problem. Look up "dl_malloc" (Doug Lea's malloc). It's a good public-domain allocator that looks like malloc and works very well allocating small chunks.
Malloc isn't a great fit if your app is constantly running out of space. In that case, find a good garbage collector or memory reordering scheme. Several garbage collectors make life easy by making allocations fast and solving the problem of free'ing memory.
Remember, don't pick an allocation scheme based on the problems you *think* you'll have. Pick an allocator whose major benefit matches your major issue.
"You need a license to buy a gun, but they'll sell anyone a stamp." - Red Green
Yes, it is possible to calculate your memory needs using dynamic allocation and deallocation, but it is a lot harder to prove and a lot easier to make a mistake. If you really can reliably put an upper bound on the amount of memory your app uses, then there is usually no need for dynamic allocation in the first place. If you don't care about predicting your memory usage or malloc execution time, then why are you even asking the question? Just go with whatever is easier. However, consider that some extra effort now will pay off in the long run.
You have to let go of your assumptions from the non-embedded world. The natural instinct is to save as much memory as possible, since your memory is so limited. Your undergrad algorithms class taught you that dynamic allocation is the way to have the lowest possible memory usage at any given time. However, in an embedded application, unallocated memory is just as wasted as extra memory allocated in a static buffer, but in the latter you always know it is available as soon as you need it.
This space intentionally left blank.
The standard way that glibc works is that the heap grows until the task ends. This can cause problems so yes dynamic memory allocation should be avoided but your question leaves out a lot of variables.
1. Does the CPU have an MMU.
2. What OS.
3. Single or multi tasking?
Without knowing more no one can give you a firm answer.
See my blog http://ilovecookes.blogspot.com/ for light hearted technical information.