Slashdot Mirror


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?"

102 comments

  1. Take your question... by HotNeedleOfInquiry · · Score: 4, Informative

    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...
    1. Re:Take your question... by RevAaron · · Score: 1

      What? c.a.e? Are you saying... you don't trust a bunch of sweaty 15 year olds to give advice on serious embedded coding?

      "Hey d00d- why not just write it in Python? Python is am embedded lang, and you can write hard math parts in C no prob mmkay?"

      "Stfu! Perl > C anyday."

      "I heard you could do embedded stuff in PILOT, with a PILOT interpreter running as a kernel module on Linux.... I know a guy who know a guy who runs Linux, so I would reccomend it holehartedly!!1"

      --

      Working toward a usable PDA environment in the spirit of Newton OS: Dynapad
  2. lol by Anonymous Coward · · Score: 0

    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

  3. Tradeoff by addaon · · Score: 3, Insightful

    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.
    1. Re:Tradeoff by MicahStevens · · Score: 2

      Agreed, there is no absolute answer here. In many cases the overhead involved with malloc() or whatever you're using is too high, or if the data structure is simple enough you don't need it in the first place. I'm used to dealing with 2-4K of memory, in which case the cards are pretty much all laid out in front of me, only in special situations would I use dynamic allocation..

      However, if you're doing a complex application and have 16 megs of memory (HUGE!) with an ARM or some higher end processor that has the headroom, I doubt it matters much, you might as well be lazy and do the easiest thing.

    2. Re:Tradeoff by ksheff · · Score: 2, Insightful

      I'm sure anyone doing DOS application development a couple decades ago would have loved a flat address space with 16MB of memory. Many applications used dynamic memory allocation then, so what's the problem with modern embedded applications? If you're getting lots of memory fragmentation, either the implementation of free() on the dev kit is broke (like it was with a version of Microsoft C in the late 80s), and/or you need to re-think the design of your application. I guess many programmers don't care much about memory usage anymore.

      --
      the good ground has been paved over by suicidal maniacs
    3. Re:Tradeoff by bunratty · · Score: 2, Insightful
      One problem is that it's often desirable for embedded applications to behave predictably. If you're using malloc, it can sometimes take more time than others, and the real-time behavior is not deterministic. Another problem is that embedded systems need to be very reliable over long periods of time with no user intervention. The smallest memory leak could lead to crashes or other erratic behavior.

      When I was programming embedded systems and was lucky enough to have actual dynamic memory allocation, I reserved using it for allocating memory at initialization and the few cases where it would have been tricky to use static allocation and deterministic behavior was not important.

      --
      What a fool believes, he sees, no wise man has the power to reason away.
    4. Re:Tradeoff by jci · · Score: 1

      I'll put in a me too on this, at least for anything more than a toy.

      In the stuff I've worked on, items like linked list were really an array with a class wrapped around it to provide the same equivalent functions. In the end it was finite (60 items) and as a result had to give exception when filled.

      But this meant that the memory could be accounted for at all times, instead of running away or being orphaned.

      In a deterministic project, the keyword "new" is always replaced by finite static instances of objects... that is if the project even bothers going into OOD. The word "dynamic" doesn't really come in to play either.

      Try to think of your data structures and see if maybe you can give it finite limit.

    5. Re:Tradeoff by cow-orker · · Score: 1

      One problem is that it's often desirable for embedded applications to behave predictably.

      Strange. This could be construed to mean that it doesn't matter whether or not a full blown desktop or server application behaves predictably. Since nobody seems to think this is wrong, something is seriously broken in this industry.

      Another problem is that embedded systems need to be very reliable over long periods of time with no user intervention.

      This is next to impossible in C, the reality of the software industry proves this day in and day out. Dynamic allocation or not, a reliable system in C takes competent programmers (at least two, one has to keep an eye on the blind spot of the other), lots of time and many iterations until the bugs are ironed out. We see this on the desktop and server, too: software simply is unreliable, and if the bugs aren't introduced by faulty memory management, there are still buffer overflows and the like.

      So I'd say it doesn't matter whether you use malloc. If reliability is that important, don't use C.

    6. Re:Tradeoff by FuzzyDaddy · · Score: 1
      The larger problem, in my mind, is potential memory leaks. In an embedded application, presumably, this thing is going to run forever. Also, not dynamically allocating memory gives you more deterministic behavior, so you can put a little more faith in your testing.

      Of course, a lot will depend on how many limitations avoiding dynamic memory will impose on your system. Keeping it to a minimum in an embedded system is always a good idea.

      --
      It's not wasting time, I'm educating myself.
  4. Why? by ObsessiveMathsFreak · · Score: 2, Interesting

    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!
    1. Re:Why? by try_anything · · Score: 3, Interesting
      I second sticking with C++. The poster may have a good reason for switching to C, but he should have explained it, because the difference between C and C++ is extremely relevant to his question! Thanks to RAII and smart pointers like boost::scoped_ptr (see boost.org) C++ is way ahead of C for using dynamic memory allocation safely and readably. Switching to dynamic allocation will likely involve much greater cost in bugs and readability if C is used instead of C++.

      Also, if performance is important, it's important to be able to experiment with allocation methods when you run into problems. In C++, the ability to implement new and delete differently for each class allows you to experiment with custom allocators without rewriting your code, even if you didn't think of it beforehand. If you use C, make sure you wrap your calls to malloc and free in case you need to tinker later!

    2. Re:Why? by JanneM · · Score: 1

      One problem with C++ is that it's difficult to know that an operation always will take the same amount of time. There can be quite a lot going on in the background whenever you create a new instance of a class, for example, and figuring that out can be almost impossible (especially if things like overloading have been used). For embedded applications (where you frequently must have an upper bound on reaction time) this can be a deal-breaker.

      Of course, if that is the case, he shouldn't be looking at dynamic memory allocation either, tfor the same reason.

      --
      Trust the Computer. The Computer is your friend.
    3. Re:Why? by try_anything · · Score: 2, Insightful

      C++ imposes hardly any run-time cost, and in most cases none at all, if you turn off exception handling and RTTI. This has been an explicit design goal of C++ since the beginning. Any problem that forces you into the situation you describe (which I think is inheritance with virtual functions) would require an equally complex C solution which would be harder to read and would probably compile to slower code since C++ compilers use implementation tricks that can't be expressed in C.

      The proof of this is that (almost) any standard C program can be turned into a standard C++ program with trivial changes (modulo some C99 stuff like complex numbers). If you can write C code that is faster or more predictable than C++ code, simply do so. Then rename your .c files to .cpp ;-)

    4. Re:Why? by NullProg · · Score: 1

      The poster may have a good reason for switching to C, but he should have explained it, because the difference between C and C++ is extremely relevant to his question!
      I agree with your post but when storage is minimal the CRT wins everytime over the C++ runtime. Nothing against C++. You do know you can OOP using C?

      Enjoy.

      --
      It's just the normal noises in here.
    5. Re:Why? by swillden · · Score: 4, Informative

      One problem with C++ is that it's difficult to know that an operation always will take the same amount of time.

      Absolute nonsense. C++ doesn't have a garbage collector or anything like that running that can introduce random delays. The same bit of code following the same path will take the same amount of time to execute every time... just like C (well, assuming you don't run into cache misses, etc. but those typically don't crop up on embedded processors.).

      There can be quite a lot going on in the background whenever you create a new instance of a class, for example, and figuring that out can be almost impossible (especially if things like overloading have been used).

      Dead wrong again. If you know the language you can quite easily see what precisely is going to happen. You might have to go read the constructor, and if the class contains other objects you might have to read their constructors, but all of that code is code that would have to be executed in a C implementation as well -- you have to initialize your data somewhere.

      C++ does impose some "hidden" costs, but the language is specifically designed to make sure they're insignificant. Virtual function invocations have a hidden cost: An extra pointer dereference, which is dwarfed by the cost of the function call, even if the function is a no-op. If you're going to worry about that cost, you should probably avoid function calls altogether. The biggest potential hit is exceptions. The compiler has to generate extra code in every function to handle cleanup in the event of an exception, and it can cost a bit. In practice, not using exceptions also costs something, because you have to write a lot more manual error handling, which also has to be compiled in, but, in general, stack frames with exception unwinding may add noticeable run-time to functions that don't do much, but do create objects that must be destroyed. If that's a concern, just compile with -f-no-exceptions and write the error-handling code yourself. Some people like to turn off RTTI also, but that's actually very cheap, and it allows for some very clean solutions to complex problems (but use it sparingly, because it's easy to abuse).

      The most likely source of apparent non-determinism in C++ code is the same in C code: memory allocation and deallocation. One way to fix that is to get a real-time implementation of malloc()/free(), but even without doing that, C++ provides great tools for making allocation more reliable: by overloading 'new' on key classes and implementing a pooled allocation scheme, you can ensure that allocations and deallocations are both constant-time and faster than any general-purpose allocator could be.

      Where C++ is a big win is in the libraries, especially the template libraries. The STL's sort routine, for example, is usually significantly faster than qsort(), and never slower. High-performance, typesafe, THOROUGHLY DEBUGGED collections implementing a variety of different data structures are a big win for any environment (though platforms with very tight constraints on code size may need to avoid them, since they can bloat the binary -- not likely an issue for our friend with 16MB RAM).

      For embedded applications (where you frequently must have an upper bound on reaction time) this can be a deal-breaker.

      For _hard_real-time_ applications, you mean -- lots of embedded apps are not real-time, much less hard real-time, you're not going to trust C, either. For hard real-time apps what you do is:

      1. Pick a processor and platform that has guaranteed maximum instruction times (which means you want to avoid a lot of cache memory and no deep pipelines that may stall badly on a wrong branch prediction).
      2. Write your code in a language that compiles to assembler/machine code.
      3. Identify the time-critical sections and calculate the cycles that they will consume. (Well, actually you profile first -- it's only necessary to actually count cycles if you're getting close
      --
      Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
    6. Re:Why? by AiY · · Score: 5, Informative

      First off, I'll just note that all my professional development career has been working with embedded systems.

      Second, I'm gonna stay out of the whole "... but <language x> is not an issue because..."

      There are many, many reasons to use C instead of C++ on an embedded system. The two biggest are
        a) Portability
        b) Stability/Conformance

      C has a much better record of consistency between embedded platforms. It carries little baggage so most vendors get it right. If the same codebase has to run on several platforms, the specific C compiler for each platform probably produces code that behaves more consistently than C++ compilers.

      Stability and confromance come from the fact that embedded vendors don't always spend the time keeping their compilers up to date, and you may be forced to used the vendor's compiler.

      As a specific case from place of business: A new project was developed entirely on an emulated environment, beautifully done in C++. Object oriented and all that - this fit the project very nicely. The code was quite stable and was continuously tested with a dedicated rig that ran a huge battery of sample cases against the product. Then the port to the first target platform began. Turns out that it wasn't x86 and Microsoft C++ didn't run there. No problem - the vendore had a C++ compiler. But wait - it didn't support complicated features like "templates" so there was fiddling. By the time I saw the codebase, there were two sets of #ifdefs - one for WIN32 (which worked) and one for the platform (which did not). Later we took that code base, stripped out a bunch of features, converted to C and had it running on about 4 different embedded architectures.

      Oh, and the low-end platform was a 25MHz 68331 with 2 MB total memory, 1.5MB total that our middleware could use, so effectively about 700 KB. And we used dynamic memory allocation.

      The moral: C compilers are simpler so they tend to be better supported. If your team is more comfortable with some other language and the target supports it, go with that. Remember that maintenance will be the major portion so the more obvious the code is to the developers the better.

      --
      "You need a license to buy a gun, but they'll sell anyone a stamp." - Red Green
    7. Re:Why? by Anonymous Coward · · Score: 0

      I agree with your post but when storage is minimal the CRT wins everytime over the C++ runtime.

      If storage is minimal, why are you using either one? I routinely code for well under 1MB of memory, in C++. No standard runtime.

    8. Re:Why? by Lord+of+the+Fries · · Score: 1

      One reason I might be tempted to stay away from C++, is once you use it, you might want to use STL or boost. C++ compilers for off-the-mainstream architectures aren't usually as good about code reduction as a maybe GCC for x86 might be. I've seen embedded communications apps go from 40Kb C executables to 1 MB for C++, all so we would be able to use STL streams and such. The problem... there's only 2MB of flash only these devices, we can't upgrade to the new uClinux because we used up so much room.

      If you really want to do "objects" in an embedded environment... why not use embedded Java or these guys.

      --
      One man's pink plane is another man's blue plane.
    9. Re:Why? by try_anything · · Score: 1
      One reason I might be tempted to stay away from C++, is once you use it, you might want to use STL or boost.

      Good idea, stay away from languages with big libraries. That way you have to use third party libraries or implement everything yourself, and then you'll know everything is correct and efficient ;-)

      I'm mostly kidding. I was going to blast you until I remembered that code size, unlike execution time, can't be dramatically improved by making isolated tweaks. I'm guessing it is not pleasant to go through your code and replace every use of a std::vector<T> or std::set<T> for some T, in order to save the memory footprint of that class.

    10. Re:Why? by thsths · · Score: 1

      > 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.

      I have written lots of embedded code, and some of it in C++ (with 512kB RAM!). You may want to be careful with template instantiation and the standard libraries, but otherwise there is little reason not to do it.

      And I notice how old I am suddenly feeling. My first (own!) PC had 4 MB of memory, and I spent a fortune on the upgrade to 8MB, so that X would run nicely. Heck, I was doing development under X11 with emacs and gcc... and I also used applications written in C++.

      So I am positive: C++ is absolutely fine with only 8MB of memory :-)

      As a sidenote: pseudo-static allocation can be extremely efficient, if done correctly. It is a bit like chuncks in glib. The right memory management for the right purpose. So for general purpose stuff (not in the critical path) you can just use malloc, why not?

    11. Re:Why? by Anonymous Coward · · Score: 0
      You do know you can OOP using C?

      if you can inherit, subclass, or have virtual functions than it's not OOP.

    12. Re:Why? by Anonymous Coward · · Score: 0

      One reason I might be tempted to stay away from C++, is once you use it, you might want to use STL or boost.

      That's a problem that can be easily solved: don't do that. There are pieces of each that have very low overhead, but much of these libraries is way over-spec'ed. You just need to have good discipline and understand the costs.

      C++ compilers for off-the-mainstream architectures aren't usually as good about code reduction as a maybe GCC for x86 might be. I've seen embedded communications apps go from 40Kb C executables to 1 MB for C++, all so we would be able to use STL streams and such.

      That bloat isn't just an inefficient compiler, it's also all the extra features in the library that you probably didn't need. Vastly over-spec'ed. Don't use STL, and only use the most lightweight Boost libraries.

      why not use embedded Java

      Ha! Don't use C++, use something slower that uses more memory.

      Non-x86 JIT interpreters are just as bad if not worse than non-x86 C++ compilers, especially if you go cheap. (OTOH, GCC is decent and free.)

      Garbage collection tends to leave you with a lot high memory usage as well, again especially if you go with a cheap JVM. This doesn't matter on "real" computers because there's so much available, and unused bits may be paged out. In an embedded system, you'll be calling system.gc() and hoping that your JVM vender actually implemented it.

    13. Re:Why? by AuMatar · · Score: 1

      OOP is about encapsulation and separating interface from implementation. Inheretance is not a necessarfy component of OOP. The vast majority of the time its the misused bastard feature of OOP more than a help.

      And C does have virtual functions- its called a function pointer.

      --
      I still have more fans than freaks. WTF is wrong with you people?
    14. Re:Why? by AuMatar · · Score: 1
      Absolute nonsense. C++ doesn't have a garbage collector or anything like that running that can introduce random delays. The same bit of code following the same path will take the same amount of time to execute every time... just like C (well, assuming you don't run into cache misses, etc. but those typically don't crop up on embedded processors.).


      Cache misses crop up on many embedded processors. But lets ignore that. The real problem is that C++ is harder to estimate the time up front than C. If you have a function and you pass it an object, it it going to call the constructor once? Twice? Once and the operator equals once? It differs by compiler.

      Where C++ is a big win is in the libraries, especially the template libraries. The STL's sort routine, for example, is usually significantly faster than qsort(), and never slower.


      You have it backwards here- templates are generally a lose for embedded. The reason is that generating n versions of the template classes/functions ends up costing way too much in ROM (which is generally tighter than even RAM). Instead you write a single version that uses void* pointers and a size field in the node, saving Ks of ram.

      As for STL's sort- its ok. But its rarely your best option. The reason is that qsort is a very good option IF you have no knowledge of the data you're sorting. Generally, you do. And using that knowledge can greatly speed up the code. For example, if you have nearly sorted data, there are algorithms with n^2 worst time but n average time.

      I'm not sure if I would rewrite an existing C++ app in C, but there are plenty of reasons to pick C over C++ if you have no existing code. Ease of debugging and better tools are the first two.
      --
      I still have more fans than freaks. WTF is wrong with you people?
    15. Re:Why? by aCapitalist · · Score: 1

      OOP is about encapsulation and separating interface from implementation. Inheretance is not a necessarfy component of OOP. The vast majority of the time its the misused bastard feature of OOP more than a help.

      Exactly, you don't lose what you don't use in C++. It's all about knowing what the costs are. Granted, there are some real small 2k-4k stuff where it might not make much sense to use C++. Then you almost get into the realm of assembly almost. But this guy has 16Mb to play around with. Ram sizes only continue to go up in "embedded" devices, while C++ compilers are a helluva lot better than they were 10 years ago.

      And I agree that inheritance is the most (mis)overused crap in any OO language.

    16. Re:Why? by swillden · · Score: 1

      If you have a function and you pass it an object, it it going to call the constructor once? Twice? Once and the operator equals once? It differs by compiler.

      No, it doesn't differ by compiler, unless the compiler is broken. The ISO C++ standard defines the semantics quite precisely.

      To answer the specific question: Pass by value? It will call the copy constructor once. Period. And when the function terminates, it will call the destructor once. But why would you pass objects by value? Do you commonly pass structs around by value in your C code? I've often wished C had an equivalent to const reference parameters, so I wouldn't have to pass pointers. That's probably because of my C++ bias, though; when I see code that passes a pointer I assume it's because the function will modify the struct.

      The reason is that generating n versions of the template classes/functions ends up costing way too much in ROM (which is generally tighter than even RAM). Instead you write a single version that uses void* pointers and a size field in the node, saving Ks of ram.

      That depends heavily on what kind of embedded system you're talking about. I seriously doubt that this box with 16MB of RAM is constrained by non-volatile memory.

      Also, although I no longer work on traditional embedded systems, I did for several years, on several different projects, and the only ones I ever saw with less non-volatile storage than RAM were the ones that used battery-backed RAM instead of ROM. I'm not calling you a liar, I'm just saying that the segment of the industry you've seen is different from the segment I've seen, and what you've seen seems very strange to me since RAM is so much more expensive than ROM, EEPROM or Flash RAM.

      And using that knowledge can greatly speed up the code. For example, if you have nearly sorted data, there are algorithms with n^2 worst time but n average time.

      Absolutely. The great thing about the STL, though, is that you can start by using the standard function, knowing it will be pretty good, and then later drop in another STL-style templatized sort algorithm by changing a single line of code, *and* there will be no inefficiencies caused by the sort algorithm not knowing what types it's operating on in either case. I once did exactly that, replaced a usage of std::sort with an STL-compliant insertion sort that I hacked out of the SGI's std::sort (The SGI implementation of std::sort uses an introsort, which is a combined quicksort and heapsort, followed by an insertion sort). The effort was minimal and speedup was significant. If I hadn't had the insertion sort handy, I could have written one easily enough; writing templatized functions is no harder than writing other genericized code, once you get used to the syntax. The compiler was able to inline all of the comparisons and helper function calls and the resulting assembler code was extremely tight and very fast.

      I'm not sure if I would rewrite an existing C++ app in C, but there are plenty of reasons to pick C over C++ if you have no existing code. Ease of debugging and better tools are the first two.

      Tools, perhaps, depends on the environment. But ease of debugging?? No way. C++'s stronger typechecking allows you to make the compiler find all sorts of problems that would be very hard to find in C. Using some smart pointers, plus a little discipline to always avoid "naked" pointers, can eliminate whole classes of memory management mistakes. In general, proper application of destructors makes your code much easier to read and less error prone.

      There are all kinds of things that programmers have to take care to do right when writing C. C++ is not fundamentally different in that respect, but C++ allows you to automate many of those potentially error-prone situations, letting the compiler make sure they're done right. During development, you can also have all of that "hidden" code (ctors, dtors, assignment operators, etc.) do lots of extra error che

      --
      Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
    17. Re:Why? by dpmedeiros · · Score: 1
      Oh, and the low-end platform was a 25MHz 68331 with 2 MB total memory, 1.5MB total that our middleware could use, so effectively about 700 KB. And we used dynamic memory allocation.
      Ah. Porting to the Motorola DCT2000 eh? I feel for you.
    18. Re:Why? by ultranova · · Score: 1

      Identify the time-critical sections and calculate the cycles that they will consume. (Well, actually you profile first -- it's only necessary to actually count cycles if you're getting close to the limit).

      I've never done hard real-time applications, so I might be wrong here; but it seems to me that trusting profiling is asking for trouble. How do you know that the longest execution time seen by the profiler is the longest possible time ? You don't. Which means that you don't know if the function might, in some circumstances, fail to execute in the allowed time, which, by definition of hard real-time, means that the whole application will fail catastrophically.

      --

      Forget magic. Any technology distinguishable from divine power is insufficiently advanced.

    19. Re:Why? by swillden · · Score: 1

      it seems to me that trusting profiling is asking for trouble.

      It can be. You have to be smart about it. But actually calculating cycles is so much work that it many cases makes sense to optimize developer time by trusting the profiler when it says that this very straightforward, non-looping function runs in 1% of the time budgeted for it.

      --
      Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
    20. Re:Why? by AuMatar · · Score: 1
      No, it doesn't differ by compiler, unless the compiler is broken. The ISO C++ standard defines the semantics quite precisely.

      To answer the specific question: Pass by value? It will call the copy constructor once. Period. And when the function terminates, it will call the destructor once. But why would you pass objects by value? Do you commonly pass structs around by value in your C code? I've often wished C had an equivalent to const reference parameters, so I wouldn't have to pass pointers. That's probably because of my C++ bias, though; when I see code that passes a pointer I assume it's because the function will modify the struct.


      ITs not that simple. Read Effective C++, and you can see all the wierd ways constructors and destructors get called. Its unobvious, and it can be a huge performance hit.

      As for passing structs by value- how big is the struct? If its 1-2 ints, its probably more efficient to pass by value (where the compiler will almost certainly optimize it to use register passing).

      ANd this is probably my C bias, but I HATE consts in C++. Nothing more annoying than not being able ot call a member function, and needing to backtrace through 7 levels of functions removing const everywhere to fix it. That feature should never have been in the language.

      That depends heavily on what kind of embedded system you're talking about. I seriously doubt that this box with 16MB of RAM is constrained by non-volatile memory.


      You'd be wrong. I've worked on many projects that had plenty of RAM, but needed to fit in tiny ROMs. 16 MB isn't much for some of the more heavyweight embedded apps- your printer has at least that much.

      Tools, perhaps, depends on the environment. But ease of debugging?? No way. C++'s stronger typechecking allows you to make the compiler find all sorts of problems that would be very hard to find in C. Using some smart pointers, plus a little discipline to always avoid "naked" pointers, can eliminate whole classes of memory management mistakes. In general, proper application of destructors makes your code much easier to read and less error prone.


      Memory problems is a boogie man. It doesn't really exist. In the past 4 years, I've seen 1 memory bug reach the main code branch. It just isn't hard to get right. Virtual functions, inheretance, and the like make it far harder to debug C++ programs than it is well structured C. They make it nearly impossible to debug without actually running the program, which isn't always an option (bug in an ISR, for example). Type checking is the only advantage of C++, and thats negated by the fact every modern compiler gives warnings in C on those bugs. Just look for and fix the warnings (you do have a no warnings policy on your code, don't you?).

      In addition, C++ designs just tend to be cruftier. Extra classes here, useless inheretance here, abstract base classes with only 1 child there, auto pointers everywhere because apparently the author was too stupid to know how to use delete. That adds up to a hit, not just on performance but on speed and ease of development and debugging.

      Now in the OP's case, where he has an existing C++ app that needs to become embedded, I'd never suggest rewriting it in C. But if I was to pick a language for a new app, it'd be C over C++ in a heartbeat.
      --
      I still have more fans than freaks. WTF is wrong with you people?
    21. Re:Why? by swillden · · Score: 1

      Read Effective C++, and you can see all the wierd ways constructors and destructors get called. Its unobvious, and it can be a huge performance hit.

      I read Meyers' book when it first came out and found it tedious and often wrong. Perhaps later editions got better, but I haven't looked.

      As far as the "unobviousness" goes, I guess I just have to disagree, with a caveat. I've been writing C++ code professionally since 1992 or thereabouts, so it's possible that what's obvious to me is not obvious to others. I readily grant that the C++ learning curve is steep.

      ANd this is probably my C bias, but I HATE consts in C++. Nothing more annoying than not being able ot call a member function, and needing to backtrace through 7 levels of functions removing const everywhere to fix it. That feature should never have been in the language.

      I completely disagree. Const-correctness is a huge boon if it's applied rigorously and thoughtfully. When you find a place where you need to call a non-const method on a const object, it's time to look at the situation very carefully. Should that method actually be const? If not, why is it that you need to modify an object that other functions up the call stack don't expect to change? This analysis often exposes broken assumptions.

      I'll grant that constness can really be a pain in the ass if you're using library code written by someone who didn't do it right. You end up having to const_cast<> everywhere you touch the broken API. Yuck.

      You'd be wrong. I've worked on many projects that had plenty of RAM, but needed to fit in tiny ROMs.

      I'll have to take your word for that. It's not my experience.

      Virtual functions, inheretance, and the like make it far harder to debug C++ programs than it is well structured C. They make it nearly impossible to debug without actually running the program, which isn't always an option (bug in an ISR, for example).

      That's entirely dependent on how you choose to write the code. If you write C code that makes heavy use of function pointers then you're in the same boat. If you need the flexibility of making code behave differently at run-time depending on what sorts of objects are being worked on, you have to accept the cost, regardless of language. C++ makes it less painful than doing it in C.

      Type checking is the only advantage of C++, and thats negated by the fact every modern compiler gives warnings in C on those bugs.

      No, it doesn't. In C you have to use builtin types because thats all you have, and one int is completely interchangeable for any other int. C++ allows you to create your own types and have the compiler verify that things match up. Read "Scientific and Engineering C++" by Barton and Nackman to get an idea how much work the compiler can do for you. Although they take it a bit over the top, they show how you can construct a system that allows the compiler to perform units analysis for you, so that multiplying a mass value by a distance value and dividing by a time value squared produces a result that can only be assigned to a force variable. Trying to assign it to, say, a work variable will result in a compile time error. And there's no run-time difference between that and just using a bunch of doubles.

      C++ gives you powerful and extensive tools for doing a degree of compile-time typechecking that nothing else can touch.

      In addition, C++ designs just tend to be cruftier. Extra classes here, useless inheretance here, abstract base classes with only 1 child there,

      Bad designs can be implemented in any language.

      auto pointers everywhere because apparently the author was too stupid to know how to use delete.

      No! auto_ptr<> _should_ be used everywhere, because the author is smart enough to know that having to manually delete things risks human error. If not of the original author, of some future engineer who adds another code path but forgets to incl

      --
      Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
    22. Re:Why? by angel'o'sphere · · Score: 1

      Seems you have no clue about C++, and thats why you write stuff like this:


      The real problem is that C++ is harder to estimate the time up front than C. If you have a function and you pass it an object, it it going to call the constructor once? Twice? Once and the operator equals once? It differs by compiler.


      First of all: you can't pass an object in C++.
      Second: if you like to do this, you either pass a reference or a pointer.
      Third if you can't do that, you indeed pass it like it is and then its like any other value, e.g. an integer, that means there is a copy created on the stack for the called function. And in this case the CTOR is called, gues what .... ONCE.

      WTF do you think a ctor could be called twice?


      You have it backwards here- templates are generally a lose for embedded. The reason is that generating n versions of the template classes/functions ends up costing way too much in ROM (which is generally tighter than even RAM). Instead you write a single version that uses void* pointers and a size field in the node, saving Ks of ram.


      Same nonsense again.

      Suppsoe you have a List Template class. How many lists do you instanciate? 1? 2? 10? With 10 lists duplication of code is no issue. With 100ds of lists probably.

      Modern C++ compiler/linkers recognize if you instanciate the same tempalte multiple times and factor out common code to save you space.

      Finally, using templates that are based on your void* solution is common practice. In this case you gain everything that templates give you and you get all advantages of the void* solution without their drawbacks.

      Go and start writing C++, its not the evil unpredictable thing your friends, who never wrote more than 100 lines, told
      you.

      angel'o'sphere

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    23. Re:Why? by angel'o'sphere · · Score: 1



      ITs not that simple. Read Effective C++, and you can see all the wierd ways constructors and destructors get called. Its unobvious, and it can be a huge performance hit.


      Obvioulsy you know that, so no one will convince you, that you only think you know that :D

      Read Steve Meyers again and you will figure that most of what you find "wierd" is only wierd if you lack knowledge. Its completely well defined under what circumstances what is happening. The problem with C++ is, that this number of circumstances easy hits 10 to 15 different situations. Nevertheless a C++ Ctor is allways ever only called once. There is NO SINGLE situation when it would be called twice. If it would, that would be really bad.


      Virtual functions, inheretance, and the like make it far harder to debug C++ programs than it is well structured C.


      This is nonsense. Debugging means you use a debugger. That means you set break points and watch the programm running and break at those break points. There you examine varibale values, stack traces, registers, memory dumps, what ever you want. Its completely independent from your language.

      angel'o'sphere

      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
    24. Re:Why? by cow-orker · · Score: 1

      when storage is minimal the CRT wins everytime over the C++ runtime

      No, it doesn't. C++ doesn't need much runtime, basically just memory management (same as in C) and some support for exception handling (optional, but worth it, imho). The rest is the standard library, and there you only pay for what you use, as in C.

      If you compare specific parts of the two libraries, C++ wins. Most striking example: C printf (ever written a program without it?) need to include all the formatting code for dealing with integers, floats, string, formatting flags, locales. How could it leave something out, for the compiler cannot see that you never use %f. C++ iostreams only need the formatting code that is actually called. You will often get rid of the floating point output, because you never output floats. You may have a single, trivial locale in your program, so you get rid of that code, too. Also, stream operations can be inlined, printf cannot.

      However, commercial C++ runtimes are often implemented as a layer on top of the C runtime. This adds to the size, of course.

    25. Re:Why? by cow-orker · · Score: 1

      If you have a function and you pass it an object, it it going to call the constructor once?

      It calls the copy constructor exactly once. If you pass a constant reference instead, nothing is called. But of course, if you *do* pass by value, you know what you're doing.

      Unless of course you're a dimwitted Java programmer retrofitted to crank C++ because the JVM was larger than the available RAM and you thought, you could code anything that had curly braces.

      (Returning an object by value calls the copy constructor at most once. If that turns out to be a problem, you return an std::auto_ptr or something similar, or you do black magic with template meta programs like in Blitz++.)

      templates are generally a lose for embedded. The reason is that generating n versions of the template classes/functions ends up costing way too much in ROM (which is generally tighter than even RAM). Instead you write a single version that uses void* pointers and a size field in the node, saving Ks of ram.

      No, you don't (even if the proponents of Java generics don't seem to ever get tired of lambasting the evil code bloat in C++ from use of templates). You write the goddamn template, give it a specialization for (void*), then partially specialize it for (T*) and implement that in terms of (void*). You get all the fun at no extra cost, you just have to know what you're doing.

      Even more important is the use of templates in the STL: yes, you generate n versions of std::list for all sorts of usually small objects. That amounts to exactly no code, because all functions defined on it are so tiny, they get inlined. After inlining, everything is ordinary static structures with constant offsets. The (void*) could never match that performance, neither in memory consumption nor in execution time. ...qsort...

      Well, most STL implementation actually use shell sort. But that's beside the point, because STL works well with user supplied algorithms. By comparison, any generic sort in C is dog slow, because it has to call out to the predicate through a function pointer. The template version in C++ can inline the predicate.

    26. Re:Why? by AuMatar · · Score: 1
      This is nonsense. Debugging means you use a debugger. That means you set break points and watch the programm running and break at those break points. There you examine varibale values, stack traces, registers, memory dumps, what ever you want. Its completely independent from your language.


      First off- we're talking embedded here. We're lucky if we have serial output. Forget about being able to run a debugger on it.

      Secondly- hitting the debugger is rarely the best way to debug a problem. It can help, but the first tool is to sit down and think it out. This is more difficult in C++ where the functions executed depends on run time type, compared to C where it does not.
      --
      I still have more fans than freaks. WTF is wrong with you people?
    27. Re:Why? by AuMatar · · Score: 1
      First of all: you can't pass an object in C++.
      Second: if you like to do this, you either pass a reference or a pointer.
      Third if you can't do that, you indeed pass it like it is and then its like any other value, e.g. an integer, that means there is a copy created on the stack for the called function. And in this case the CTOR is called, gues what .... ONCE.


      Umm, you sure as hell can pass an object in C++. Go ahead, code up a test.

      For the third issue- read Meyer's effective C++, and see all the hidden places operator = and constructors can be called.

      Modern C++ compiler/linkers recognize if you instanciate the same tempalte multiple times and factor out common code to save you space.


      This is embedded programming. Modern compilers don't exist- embedded compiler tech typically lags by most of a decade. You also miss the problem- if I have an int version, a string version, and 3 object versions that means the template code is included 5 times (once for each version). A void technique includes it one time. When tight on ROM, that matters.
      --
      I still have more fans than freaks. WTF is wrong with you people?
    28. Re:Why? by Anonymous Coward · · Score: 0

      Maybe the guy just doesn't like C++ because it looks like ass and is convoluted to use. Do you really think a callout to a function pointer is that heavy in this day and age?? What are you gonna shave off by inlining on a 10 million element sort, a couple of seconds?? A half minute?? This is your idea of "dog slow"?? You are much better off working against code you are comfortable with that makes conceptual sense. I personally like the func pointer solution because it is clean and clear. The time lost due to this can always - ALWAYS - be made up in other areas where C really excels. I personally think the benefits of C vs C++ net out to a wash by the time its all said and done.

    29. Re:Why? by petermgreen · · Score: 1

      Forget about being able to run a debugger on it. /me looks at the blue device shaped like a hockey puck made by microchip thats on his floor.

      true its a little on feature poor side compared to a modern desktop debugger but it certainly exists.

      --
      note: i'm known as plugwash most places but i screwd up registering that here somehow in the past and now can't register
    30. Re:Why? by Anonymous Coward · · Score: 0

      cow-orker, for your post comparing performance of printf and iostream, you have been found guilty of inciting premature optimation.

      Put your hands over your head and step away from the keyboard. Remain calm. The geek police will be arriving shortly to confiscate your computer. Have a nice day!

      p.s. FWIW, iostream actually performs horribly. Try reading the STL templates or using a debugger sometime. You'll catch it doing braindead stuff like inserting data into the stream one byte at a time.

      If you're trying to do something fast, don't use printf or iostream. Roll your own. However, you should never do so unless you've profiled your application and found that printf/iostream is your bottleneck (*this will almost never be the case unless you're running a debug version of your program that is a bit too verbose in its logfiles, or if you're competing for the fastest runtime on "99,999,999 bottles of beer on the wall".)

    31. Re:Why? by AuMatar · · Score: 1

      THey exist for some platforms, assuming your hardware has the necessary special ports. Not always the case.

      --
      I still have more fans than freaks. WTF is wrong with you people?
    32. Re:Why? by Spy+Hunter · · Score: 1

      Why were you forced to use the vendor's compiler instead of GCC?

      --
      main(c,r){for(r=32;r;) printf(++c>31?c=!r--,"\n":c<r?" ":~c&r?" `":" #");}
    33. Re:Why? by __aagujc9792 · · Score: 0

      "Turns out that it wasn't x86 and Microsoft C++ didn't run there. No problem - the vendore had a C++ compiler. But wait - it didn't support complicated features like "templates" so there was fiddling." No, the vendor didn't have a C++ compiler. It didn't support templates. Of course, until Herb Sutter got his hands on it MS didn't have a C++ compiler either.

    34. Re:Why? by cow-orker · · Score: 1

      Oh come on, it wasn't me who brought up the supposedly heavyweight C++ runtime. The whole point is, printf is braindead, iostreams are sane.

      You'll catch it doing braindead stuff like inserting data into the stream one byte at a time.

      No, you don't. You catch it putting single bytes into a buffer (yes, I did look at the code). And these calls can be inlined (while printf("%c",...) cannot). Any more strawmen you want to put up?

    35. Re:Why? by angel'o'sphere · · Score: 1
      I wrote: First of all: you can't pass an object in C++.
      Second: if you like to do this, you either pass a reference or a pointer.
      Third if you can't do that, you indeed pass it like it is and then its like any other value, e.g. an integer, that means there is a copy created on the stack for the called function. And in this case the CTOR is called, gues what .... ONCE.


      You wrote:

      Umm, you sure as hell can pass an object in C++. Go ahead, code up a test.


      No, you can't. If you attempt that, a copy is created, as I said in my original post. Just try to take the adress of the passed object outside of the function and inside, so you see. Either *your* copy constructor is called -- as I pointed out, and that was the issue, *once* -- or a compiler synthesiced copy constructor is called, *once*.

      You wrote:

      For the third issue- read Meyer's effective C++, and see all the hidden places operator = and constructors can be called.


      I do C++ far longer than Scott Meyers, no offense. And I don't need ot reread it, I know all places where a operator = or a copy ctor is called.

      The point is not whether a copy ctor is called or not, but wether it is called *once* as I said, or multiple times as you said. Its never called multiple times. Calling a copy ctor in general is not more expensive than calling memcpy. So its up to you to descide if you want to pass something as "value" in C as well as in C++ and its *you* who is implementing it, so C++ is not to blame.

      I wrote:
      Modern C++ compiler/linkers recognize if you instanciate the same tempalte multiple times and factor out common code to save you space.


      You wrote:

      This is embedded programming. Modern compilers don't exist- embedded compiler tech typically lags by most of a decade. You also miss the problem- if I have an int version, a string version, and 3 object versions that means the template code is included 5 times (once for each version). A void technique includes it one time. When tight on ROM, that matters.


      Then you either have no C++, then our whole discussion is pointless, or you have it.
      If you have C++ you use a class based on void*, as you proposed and as I agreed on. Then you write a Template class with inline functions wrapping that void* base implementation.

      Thats why I mentioned this option for cases where the compiler/linker is not smart enough to factor out common code.

      And if you base it on a common class either via inheritance or via delegation, NO YOU DON'T HAVE 5 DIFFERENTE VERSIONS THEN.

      People like you are scared from what Scott Meyers writes .... WHY?

      Why don't you think: uh, ohm, if I had to write a C++ compiler, a compiler that spits out C code ... well, if I had to write one, how would I implement this or that?

      You would see pretty easy:
      a) this is how modern C++ is doing it
      b) this is how I would write my own C++ "translator"
      c) this is how I code it currently in C
      d) oops, the difference between b) and d) is rather small or non existing and a) is even more effective

      You learn C++ by considering the question above all the time. And you learn better C as well by that.

      angel'o'sphere
      --
      Cost free eBook I read (by iBook/Kobo/Amazon/ObookO/Gutenberg etc.): "The Green Odyssey" by Philip Jose Farmer.
  5. Is this a Trick Question? by NullProg · · Score: 2, Informative

    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.
    1. Re:Is this a Trick Question? by MisterPinchy · · Score: 1

      We also need to know what kind of timing performance you need. If you absolutely need to eek out all the speed you can, you better stay away from malloc/new except on startup.

  6. Uh... by Threni · · Score: 1

    Depends on whether you need to use it or not. Do you? Only you can tell!

  7. Gee Only 16MB? by Q-bert][ · · Score: 1, Flamebait

    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.

    1. Re:Gee Only 16MB? by SiggyTheViking · · Score: 2, Funny

      We need a new moderation category:

      Grumpy

      Trouble is, I can't decide if it should be +1 or -1.

    2. Re:Gee Only 16MB? by NullProg · · Score: 1, Insightful

      Moderators shouldn't moderate if they don't understand the topic. Parent is not offtopic.

      Meta-Moderators do your job.
      Enjoy.

      --
      It's just the normal noises in here.
  8. About this particular subject? I feel funny! by hackwrench · · Score: 3, Insightful

    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!

  9. Take exactly what you need by try_anything · · Score: 2, Insightful

    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.

  10. I dont care, but.... by Creepy+Crawler · · Score: 1

    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".

    --
    1. Re:I dont care, but.... by ksheff · · Score: 1

      I guess the helpdesk couldn't think of "rename the file to only use ASCII characters" or something similar. Probably not on their script.

      --
      the good ground has been paved over by suicidal maniacs
    2. Re:I dont care, but.... by Anonymous Coward · · Score: 0

      better yet, don't buy POS hardware, dumbass

    3. Re:I dont care, but.... by Creepy+Crawler · · Score: 1

      First to the poster who said "dont buy garbage", it was a gift from my girlfriend, so taking it back was hard...

      As to you about renaming the files, well, the device bootstrapped and scanned all the mp3s and wma's. While booting, it hits the bad names and crashes.

      The USB disk was accessable AFTER booting of the RCA Lyra.

      So, no renaming for you.

      Other than crashing on a "bad file name", it wasnt that bad, but no memory slot (I then got one with a memcard slot).

      --
    4. Re:I dont care, but.... by Anonymous Coward · · Score: 0

      then your girlfriend is a moron who buys garbage.

    5. Re:I dont care, but.... by ksheff · · Score: 1

      that sucks. too bad there wasn't a way to bypass the scanning of all the files.

      --
      the good ground has been paved over by suicidal maniacs
  11. what i would do by fred+fleenblat · · Score: 3, Insightful

    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.

    1. Re:what i would do by Gopal.V · · Score: 1
      > * don't allow, or at least discourage, "little" mallocs like strdup() or allocation of singleton structs.

      You have no IDEA, how hard that is to debug. I have been working on something which has two allocators and am trying to work out which one to use for a case - when I find that a guy has used strdup() completely freely without thinking whether that codepath needs shared memory or local process heap. And sadly he got it right, so I have to write yet another 200+ line function duplicating the functionality with shared memory - because I don't own that code.

      Now you know why people enjoy working on open source ... because corporate code culture is too restrictive and depressing.
  12. Black Art by ipoverscsi · · Score: 2

    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.

  13. Cluestick by Anonymous Coward · · Score: 0

    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++ :

    // using comprehensive polish notation
    MyClass *pPrivatePointerToMyClass_PointerToMyClassPointer = new MyClass;
    ...
    profit();
    delete pPrivatePointerToMyClass_PointerToMyClassPointer;

    or in C:

    struct my_struct *the_beer = malloc(sizeof(struct my_struct));
    ...
    profit();
    free(the_beer);
    Simple, see?
    1. Re:Cluestick by try_anything · · Score: 1

      First, given the C++ code above, you merely need to reimplement the new operator, and voila, you're using a different allocation scheme, possibly with extra debugging code that you can compile in when you want it.

      Given the C code above, you have to search and replace on malloc and free if you want to tinker with allocation. Very bad.

      Second, a C++ programmer would not write that C++ code. He or she would use std::auto_ptr or boost::scoped_ptr instead of calling delete.

    2. Re:Cluestick by Anonymous Coward · · Score: 0

      No shit sherlock. And most object-oriented C programmers would write allocators for their objects anyways, ala my_struct_new().

      But my example was simple to demonstrate my point, which is that the fundamentals of allocating/deallocating memory are exactly the same. So shut up and save your flames for someone else.

    3. Re:Cluestick by try_anything · · Score: 1

      You missed the point about omitting delete. C++ programmers only write deallocation code in a very few carefully examined places; everywhere else, they use RAII. C programmers have to manually pair allocation and deallocation, AND they have to take care of the error-handling cases by hand.

    4. Re:Cluestick by Anonymous Coward · · Score: 0

      Point granted, but silly.

      Whereas I'm sure that someone somewhwere has a good reason why auto_ptrs are a good idea, my original code example obviously doesn't demonstrate it. The reasonable thing to have done in my example (seeing as how everything is contained within a single scope) is to use an auto variable.

      This is whay auto_ptrs make little sense to me. If you need somehting only within the confines of your current scope, use an auto. If you're allocationg something that you want to stay around for a while, use the heap, and bloody well _pay close attention_ to your allocations/deallocations. Above all, use a tool to catch memory leaks and spurious deallocations when you test. 'Dumbing down' pointers isn't the answer to anything.

    5. Re:Cluestick by try_anything · · Score: 1

      I can see your objection to auto_ptrs.  They're most often used as class members (for which boost::scoped_ptr is superior, IMO), which doesn't apply when comparing to C.  They're mostly useful for polymorphism, or when a function returns a pointer that the caller is supposed to deallocate.  Here's an example similar to code in my current project:

      void process_file(const string& filename)
      {
          boost::scoped_ptr<DataFile> file(open_data_file(filename));
          // process the file, possibly throwing an exception for a malformed file
      }

      (The main difference between a scoped_ptr and auto_ptr is that a scoped_ptr is noncopyable, so you're less likely to do something with it that you don't expect.)

      Different classes are used to process different types of files, so an ABCFile would be created to read "foo.abc" and a DEFFile would be created to read "foo.def".  The open_file function (provided to me in a library) takes care of that.  In case of a failure, this function doesn't care about the exact reason, it only cares that resources are cleaned up and the reason for the failure (encoded in the exception) is propagated to the caller.

      As you see here, interfaces between libraries usually aren't as safe as they could be.  In this case, the open_file function returns a raw pointer, which could easily be leaked.

    6. Re:Cluestick by Anonymous Coward · · Score: 0

      C programmers have to manually pair allocation and deallocation, AND they have to take care of the error-handling cases by hand.

      So what? It's not like that's hard to do. The problem is when you get C++ or Java programmers mucking around with C code and they have to be reminded to free any memory they allocate because they're used to a garbage collector or some special library doing it for them. They probably also rely on Mommy to pick up the basement for them and to remind them to wipe their own ass, but that's another topic.
    7. Re:Cluestick by Anonymous Coward · · Score: 0
      It's not like that's hard to do.

      That's why C programs don't have memory bugs, right?

      Have you ever wondered what Java, Python, Lisp, modern C++, etc. programmers do with all the time that you spend debugging memory issues? Sure you have, because if you had enough imagination and ambition to actually do something INTERESTING instead of playing little games with pointer arithmetic, you would have given up on C long ago.

      Admit it, you're stuck on C because without a bunch of finicky little trivial problems to solve, you wouldn't have a CLUE what to do with your life. Allow me to suggest writing your code in Java and using all the time you have left over to work crossword puzzles.

    8. Re:Cluestick by AuMatar · · Score: 1

      And in C, you just remove the #include "mem.h" with #include "my_mem_lib.h". THen call your functions malloc and free.

      --
      I still have more fans than freaks. WTF is wrong with you people?
    9. Re:Cluestick by Anonymous Coward · · Score: 0

      Aww-- poor baby needed the comfort of type-safety and garbage collection to do any real work. Generalizations are bad, dude. Whatever shitty fanboyism you have going on, I can guarantee there are enough fanatical C programmers who could run circles around you in abstract computer science to fill several full-scale auditoriums - probably many of my students among them. This is absolute fact.

      I'm sure you're very impressed with the alternatives, and I'm sure (format t "hay look guys im not usin C bcuz im da shit lol") has you enamoured, but in the real world of embedded development? Nobody gives a twenty-second-long fat virginal anime-fan fuck about your little tinker-toys.

      Donald Ferrone
      Professor of computer science

    10. Re:Cluestick by Anonymous Coward · · Score: 0

      This is cute. I'm sure a C-Sci professor would attach his name to this profanity riddled embarassment of a post. And by the way I completely agree with you.

  14. speed by csbrooks · · Score: 1

    '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.

  15. I think in many situations you have no choice by WolfWithoutAClause · · Score: 3, Informative
    I worked on a *big* embedded telecoms project, with about the same amount of memory available; where initially we used dynamic memory as little as possible. Eventually though, we used it almost everywhere, and the places where we hadn't used it were rather awkwardly written and a source of bugs.

    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!"
  16. All about the frags by mcgroarty · · Score: 4, Insightful

    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.

    1. Re:All about the frags by aspx · · Score: 1

      Fragmentation is a problem if you do small allocs/frees frequently, but then need to do a large alloc. It is possible to design around that. For example, large objects can be preallocated.

  17. I don't know, but here's a guess by dtfinch · · Score: 1

    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.

  18. Take a step back, try something else by pslam · · Score: 4, Informative
    My company is porting our C++ Windows app to C in an embedded device

    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).

  19. No definitive answer... by stienman · · Score: 1

    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

  20. To Dynamically Alloc or Not by AiY · · Score: 5, Informative

    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
  21. more please by embedded_C · · Score: 1

    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?

  22. Have we come to this? by Anonymous Coward · · Score: 0

    Do C coders really have to post AC on slashdot in this day and age?

  23. Static, if you need reliability by kbielefe · · Score: 3, Informative
    If you're going for high standards of reliability like DO-178B certification, then the guidelines are usually to statically allocate as much as possible, use malloc if unavoidable, but never free the memory. This goes contrary to everything they drill into you in college, but it makes the maximum memory usage easily measurable and predictable and also makes the execution time of malloc very consistent. And trust me, you find memory leaks fast.

    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.
  24. Memory Fragmentation by Anonymous Coward · · Score: 0

    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.

  25. Safety Critical by Keick · · Score: 1

    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 :)

  26. I've been bitten by malloc in embedded systems by oldCoder · · Score: 1
    One big problem is handling the case when malloc returns 0 for no-more-memory. In hard real time there simply is no way to allow this to ever, ever happen.

    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
    1. Re:I've been bitten by malloc in embedded systems by Anonymous Coward · · Score: 0

      >One big problem is handling the case when malloc returns 0 for no-more-memory. In hard real time there simply is no way to allow this to ever, ever happen.

      I don't mean to pick on you, but your post sparked my desire to post. You speak of hard realtime, and you condemn malloc because it's possible to run out of memory. Let me ask this question: what happens when you run out of static/heap memory in a hard realtime system?

      That was a rhetorical question. The answer is: you lose data. There simply is nothing you can do when you've received more input than you have space available. Therefore, it does not matter whether you "malloc" or whether you use a circular buffer or fixed size stack. If you run out of space, you run out of space. There's nothing you can do about it except lose data. It's up to your application to determine where to lose that data (oldest, newest, random, by priority, etc).

      This whole thread is a red herring. The concept of "dynamic memory" is just a method of managing static memory. Whether you're in a single process or sharing among processess/threads, memory is a limited resource. Malloc/sbrk is a method of saying "hey, I need to try to claim exclusive use of N bytes/pages of ram". As the parent suggests, you could just preallocate a ton of buffers, pass them out like candy and recycle them when you're done. Guess what: that's a form of dynamic memory.

      Nothing to see here. Mod the whole thread -1, "does not understand the most basic concepts of computing".

    2. Re:I've been bitten by malloc in embedded systems by oldCoder · · Score: 1
      Yes, a simple free list can be called dynamic memory. And in either case, when you run out of memory you can lose data. With pre-allocation, you can experimentally determine how much memory you need and absolutely prevent running out of memory at a critical time. Instead, if you don't have enough memory, you get a nasty message at system boot. This is something you can fix in the lab before you inflict it on the customers. With more dynamic malloc/free, you might not discover the trouble until a problem happens in the field.

      Furthermore, when using malloc/free, you use up time non-deterministically. Simple free lists are practically instantaneous and easily used in a multi-threaded environment. Indeed, one important use of "Dynamic" buffers is to send data from one thread to another. Multi-threaded malloc/free is a real bear. It has been done, but mainly on PC's and such. See this company for a good multi-threaded malloc/free library that is really good for PC applications. Hard real-time systems are a different matter. When you absolutely positively must take action in the next few microseconds you just have to do things differently.

      Also, with malloc/free, your application is more likely to go belly up as you try to malloc more memory in the process of recovery. Or as you fail to free everything you need to in the process of recovery and leak memory.

      With roll-your-own simple free lists it is much simpler to reclaim stuff and start the failed operation over. What I failed to mention is that I would always take a buffer/block from the free list and immediately insert it on some other linked list whose head I control. That way I have a very simple way to reorganize all of memory in constant time, by appending one list to the end of another -- in the worst case.

      And, of course, it all depends. There are some embedded apps that can live with GC and some that can live with well-used malloc/free. But there are some that simply can't afford either one. Of these I wrote.

      And if you read my post carefully, I wasn't banishing malloc/free to the woodpile, just to the beginning of operations: at system boot up or possibly at the opening of a port or other major connection. The core requirement is avoid having to malloc/free in alternation with handling interrupts -- one can simply run out of time. Think of coding a device driver, you don't malloc/free in between reading disk blocks, you pre-allocate a series of disk buffers and use them in turn.

      --

      I18N == Intergalacticization
  27. malloc and glibc by LWATCDR · · Score: 2, Informative

    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.
  28. My feeling... by joto · · Score: 1

    ...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.

  29. Exceptions by Anonymous+Brave+Guy · · Score: 1
    The biggest potential hit is exceptions. The compiler has to generate extra code in every function to handle cleanup in the event of an exception, and it can cost a bit.

    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.
    1. Re:Exceptions by swillden · · Score: 1

      That's awesome! What compilers perform this optimization?

      --
      Note to ACs: I usually delete AC replies without reading them. If you want to talk to me, log in.
    2. Re:Exceptions by Anonymous+Brave+Guy · · Score: 1

      Sorry, I'm not sufficiently expert to tell you for sure who's implementing the technique already. IIRC, I first saw it described in some sort of research paper. It was a while back now, but I think it came out of somewhere like HP or Microsoft Research.

      I'm pretty sure it's also been mentioned in discussions on a couple of the more serious C++ Usenet groups, so you might like to search archives of things like comp.lang.c++.moderated if you're interested in more details. If nothing else, there's probably a thread that cites the original paper I mentioned, because that's probably how I found it.

      Sorry I can't be more specific.

      --
      If you disagree, post your argument. (-1, Overrated) isn't your personal censorship tool for views you don't like.
  30. Easy and not easy ... by angel'o'sphere · · Score: 1

    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.
  31. Oh yeah, but in reality... by cow-orker · · Score: 1
    you need to use some sort of error handling. Now it looks like this in C:
    struct my_struct *the_beer = malloc(sizeof(struct my_struct));
      int it_broke = 0 ;
      if( the_beer ) {
    ...
      it_broke = profit();
      free(the_beer);
      return it_broke ;
      }
      return 1 ;
    But in C++:
    auto_ptr<my_struct> the_beer = new my_struct;
      profit();
    See the difference? Same profit much sooner and someone even does the cleaning up for you.

    1. Re:Oh yeah, but in reality... by Hal_Porter · · Score: 1

      TANSTAAFL dude.

      It's easy to build a C++ system with what looks like nice clean code. And it works fine when you run it in your debug environment, usually as an emulation in Windows. Then you build for target and it fails 1% of the time because of some subtlety like exceptions being thrown in a constructor in a wierd error case or something. And here you have no JTAG and hence no debugging, so the only thing you have is printfs to the serial port. Which alter the timing enough to hide the bug.

      Of course, big C systems can die in hard to debug ways too, but at least then it's a real problem, like interrupts being disabled too long or something, rather than some harmless looking error handling code someone wrote without thinking.

      And a lot of C++ isms can produce really subtle bugs:
      http://blogs.msdn.com/oldnewthing/archive/2004/04/ 22/118161.aspx

      And it's worse in a complicated embedded system where you have big chunks of third party binary code, no MMU to keep the heap defragmented and hard real time constraints.

      --
      echo -e 'global _start\n _start:\n mov eax, 2\n int 80h\n jmp _start' > a.asm; nasm a.asm -f elf; ld a.o -o a;
  32. Re:Tradeoff -- Don't use C by oldCoder · · Score: 1
    I have personally created several extremely reliable apps in embedded hard real time systems. It is not easy.

    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
  33. Re:Tradeoff -- Don't use C by cow-orker · · Score: 1

    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.

  34. Meager advice by hugg · · Score: 1

    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.