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...
Embedded? You said embedded, ok. But then you're talking about 128Mbits of RAM. That's not embedded! In embedded, we're talking about single bytes of RAM! :O
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.
Depends on whether you need to use it or not. Do you? Only you can tell!
Wow you're just so limited. Bah, when I started learning C I used dynamic allocation and the computer didn't even have 1MB of memory. So wtf are you complaining about? I wouldn't consider 16MB an embedded device. I call that a high end 386 or low end 486. Hell they used to sell the first pentiums with only 8MB of ram and windows 95 on it. Geeze.
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.
Dont do stupid stuff with your hardware that makes it crap out if you copy a "bad file name" onto it.
I had a dumb-as-shit problem with the RCA (real crappy audio) Lyra. I had some non-English file names, which every OS handles, as does any usb media.
Unlike every other MP3 player, this one CRASHES on reading the filename. I called RCA's helpline about getting it not to crash. They said "Take it back, we dont know how to help with that".
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.
Why have I seen this twice already here? There is really _very little_ difference between dynamic memory allocation in C/C++.
It's new and delete vs. malloc() and free(). Custom allocators may be easier to define in C++ (a bit), but anyone using the standard library allocators is dealing with basically the same thing.
e.g. in C++ :
or in C:
Simple, see?'we have plenty of RAM - 16MB - so why not use dynamic allocation' It's not just about RAM, it's about speed. malloc() is slow enough even on, for instance, the PS2 cpu (EE) to make it worth avoiding whenever possible. If you have to do it, consider writing your own memory manager, or adapting someone else's. malloc() does a lot of complicated stuff you may not need, and in this case simpler may be a lot faster. Also, you can go a long way with pools of fixed size objects, where the pool mallocs when it needs more, and when you tell the pool you're done with an object it gets reused later.
Game Company Database
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.
If the system can do page remapping (is that the right term?), then dynamic allocation is acceptable for the most part. Non-contiguous free pages can be grouped together to satisfy requests for large contiguous chunks of ram. malloc() is pretty fast in some implementations. A very, very fast alternative you can try in some cases is alloca(), which in gcc is an intrinsic function that produces only around 2-3 instructions that allocate a variable amount of ram from the stack, which is freed when the function exits.
Something else of interest is Java. It'll be slow, but its garbage collection compacts, so that you can allocate chunks of memory up to your total free, not limited to the largest contiguous block, and without any waste caused by fragmentation. Allocation is also very fast, since free memory is kept in one contiguous chunk, which it pulls from linearly until it needs to do another garbage collection. I'm not saying to use Java, but a garbage collector in that style overcomes the severe fragmentation problem that comes with having a system that doesn't support page remapping.
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).
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...?
You're asking if there's a definitive answer on whether your particular application should use dynamic memory allocation?
Apparently not. If you don't have the definitive answer, what makes you think we will?
You won't find a definitive answer on whether dynamic memory allocation is good in general because both approaches are valuable in different situations. Sometimes it's clear - if the OS loses important significant performance using dynamic memory, or the application doesn't need dynamic memory then, in general, it's better to avoid dynamic memory for a host of reasons - performance, ease of debugging, increased determinism in program operation.
If there's no performance penalty, and the application development is significantly sped up by use of dynamic memory allocation (especially in complex programs) then it is an easy win for dynamic allocation.
This is not a situation where one is intrinsically better than the other, and you haven't given us anywhere near enough information to even guess.
However, if you have to keep explaining your reasoning then either
1) You are working with people who don't understand embedded software design (or the application) or
2) You are likely wrong to choose static allocation
In either case you may be making the problem worse by forcing others to work with a set of limitations they don't understand or can effectively work with.
-Adam
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
I agree with other posters in that we would really need to know more about the project before we could give the answer that is best for your particular set of problems. However, my first inclination is to say "no" to dynamic memory allocation in an embedded application. Can you provide more details on the device?
Do C coders really have to post AC on slashdot in this day and age?
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.
Why not dynamically allocate? If you plan to have this device run indefinitely, then you will run into memory fragmentation issues after a few days of allocating and deallocating. This will mean you will come to a point where you will segfault after a bad malloc. And you will try to figure out in your code why.
These bugs are awfully hard to track down because they aren't in the code, per se. Also, they take days or weeks to reproduce.
Again, this is merely an issue if you expect your device to be run that long. It doesn't apply to something like e.g. an anti-locking braking system that will run at most 20 hours. It would be an issue for a fire alarm system.
2 Points:
:)
1) A lot of clients in the embedded aviation world that still use C, like to follow SaferC and MISRA guidlines. SaferC basically says, dynamic memory allocation can be bad, but not using it when needed is worse. The point was that a lot of modern algorithms and designs rely on dynamic allocation. If this applies to you, then you will have more problems as a result of trying to fit them into a static allocation methodology than you would of had by using dynamic memory in the first place.
2) Lockheed Martin is using C++ for all the code on JSF (F-35). Not C, not JOVIAL, not Ada. All embedded flight software will be coded in C++. Granted, they contracted Bjourne Stroustrup to define a subset of C++ that was considered safe for safety-critical systems. And yes, dynamic allocation is in the subset
One workaround is to only use malloc when the system boots or maybe when a port opens (free when the port closes). The benefit is you can guarantee you cover the case during testing. For buffers and messages malloc at system boot a fixed number of buffers of a fixed size. Put them on a simple free list. Use them by pulling one off the free list and free them by putting them back on the free list. Never un-malloc them with free() (typically).
The nature of hard real time is that you absolutely have to handle the worst case without terminating the application. You need to know you have enough memory before you let the box out of the factory, you cannot just discover during use you need more memory, and force the user to close the email program or the web browser.
The experience from which I speak is development of telecom and user productivity boxes (like printers) that had to operate completely unattended. If your box has a user always present to take corrective action then your constraints are probably relaxed. However, if you want appliance-level reliability your constraints are not relaxed. Malloc/free is for mere personal-computer-level reliability.
The original need for malloc/free was to save memory space. That becomes less important as memory gets cheaper.
I18N == Intergalacticization
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.
...is that you ask the wrong question. Whether people "feel good" or "feel bad" about dynamic allocation in "embedded applications" is completely uninteresting to you. What is interesting is whether it makes sense for your embedded application. And given the overwhelming lack of information you have provided about your project, the answer to that can only be known by you.
I don't have time to write a long comment here, but I'll quickly note that the above isn't necessarily true any more. Modern compilers are pretty good at generating efficient code for exceptions. Although to the programmer they're quite an open-ended design tool and might be thrown in many places if you don't know exactly what someone else's code does, to the compiler they're quite deterministic: only certain places can ever throw exceptions and only certain places can ever catch them. Hence all the stack unwinding can be done in only a few places, not necessarily directly linked to the functions where the automatic variables are used.
As a result of such techniques, using exceptions is almost invariably better than propagating return codes manually. It's the usual deal: give the compiler more information, and it can better take advantage of it. The bulk of your code may actually run faster, because there's no need to test for and propagate return codes at each stage, and the overheads for exceptions are incurred only at the point of throwing.
If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
The question is ot easy answered ...
But the development is easy approached.
Instead of thinking wether you write x = malloc (size(x)); you simply do: x = new_X();
So, you write helper functions that "allocate" you a abunsh of memory when you need it. The helper functions of course use dynamic allocated memory and do nothing else but call malloc(). For every allocating function like new_X() you write a deallocation function delete_X() as well, that one obviously only calls free().
So you get a "running" system pretty fast and don't need to worry from start up what the correct solution would be.
Finally you replace the implementation of the new_X() and delete_X() functions for the types X, where you are not comfortable with malloc/free, with implementations that suit you better. E.g. like a management for a hughe enough fixed allocated array. If you fear calling extra helper functions costs to much, get a better compiler, use inlining or a macro.
angel'o'sphere
Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
You don't do it by coding the way they tell you to in CS school (by and large). And you don't do it by coding the way many self-taught programmers hack it up. It's a combination of a good CS education and experience.
C has a lot of problems but the alternatives all have problems of their own. C++ is not straightforward and can lead to over-reliance on the heap. There are ways to work around this and people do it. C++ compilers are often not built to support machine-level coding. Take a look, for example, at Microsofts discussion of Windows Device Driver coding on their web site. The list of rules to use when trying to use C++ for device drivers is daunting.
Java is making inroads in some parts of the embedded world but just doesn't have what it takes to own it. We don't have a magic bullet yet.
The realistic approach is to partition the problem into a hard-real-time portion and a more normal portion, which usually contains the user interface. One good way of partitioning is to use separate CPU's for the real-time and the user interface. Perhaps another to manage storage, perhaps not.
Sensible real-time programming tries to do as little as possible in the real-time environment and as much as possible in the more normal environment, because coding is easier there. One result is that real-time coding can be repetitive and unimaginative. This is why I got out.
I18N == Intergalacticization
You don't do it by coding the way they tell you to in CS school
I wish that was true. They don't tell you about coding in CS school at all, which is a shame. Sometimes they throw buzzwords at you and call that coding, which is even worse. So yes, due to lack of any serious programming being taught, writing robust/working/efficient, basically just good software takes a background in CS and then lots of experience.
C...C++...Java
Was that supposed to be an exhaustive list of all programming languages? I certainly hope not. Imnsho, Java belongs more to the problem set than the solution set, C++ is kind of always the second best tool, but rever really suited, and C is good for simple logic that has to be very efficient or close to the metal. More complex logic quickly gets messy in C, and in C++ as well.
I was actually thinking of Lisp, Scheme, Erlang, Lua and some others. Erlang shines in realtime embedded applications (an ATM switch does count, doesn't it?), the others are available as tiny and powerful interpreters that work well with some pieces done in C.
Couple observations from using C++ in embedded soft-real-time systems (and games):
* The smaller your subset of C++, the more portable. You can make a perfectly functional C++ app without using operator overloading, RTTI, exceptions, even virtual functions.
* The smaller your subset of C++, the less bugs that you'll blame on the compiler but will turn out to be your misinterpretation of the language (this applies unless you're Stroustrup, or maybe the author of more than one C++ compiler)
* Stack allocations and constructors/destructors are good.
* Little features like 'const' and references (basically pointers that you can't re-assign and can't be NULL) can be handy.
* STL is handy in small doses, but don't overdo it. You'll get error messages that no mortal can parse.