4

I have to write white complex application for embedded device in C. Runtime (libc) does not support malloc/calloc/realloc/free or any other kind of dynamic memory management.

What are best practice for such cases?

Edit:

Application is complex. for instance, it should do public key cryptography. Device is specific ARM-M0 based module. Compiler is 4.6.0 in C99 mode. It is bare metal (no OS), 64K of memory. I do not care about portability.

adontz
  • 1,428
  • 16
  • 36
  • 6
    What kind (and size) of application are you writing? For what device? With what compiler and what standard? (Free standing C99?) What operating system (or is it on the bare metal)? How much memory? Do you care about portability? Please **edit your question to improve it**... it is really too vague (the answer would be very different on a 16 bits microcontroller with 4Kbytes of RAM and on a Raspberry PI, or for an artificial heart driver vs some fancy furniture gadget) – Basile Starynkevitch Feb 06 '15 at 14:17
  • 1
    It's simple really. Use stack for temporary data, and global variables for non-temporary variables and big buffers. Or if you can afford big stack, you can even allocate temporary buffers there. – user694733 Feb 06 '15 at 14:24
  • If you have a lot large data structures that's usage comes and goes, it can actually be *preferable* to put them on the stack. Uses less space total. Also, another very common, and powerful technique is to use pools of buffers / structures managed via a linked list or similar to deal with many situations where malloc would normally be used. And be sure to mark your "global" variables `static`, but that should go without saying regardless of memory strategy / constraints. – Brian McFarland Feb 06 '15 at 14:38
  • @BasileStarynkevitch - If he's on something Raspberry PI like, he almost certainly has dynamic memory allocation available and if he's working on an artificial heart, "best practices" will be heavily enforced by project lead & QA. I'm guessing cortex-m0/m3/m4 sorta stuff. But agree, clarification is needed. – Brian McFarland Feb 06 '15 at 14:42
  • 1
    You might want to consider an RTOS if the application is complex. Good options for you target HW include: CooCox, FreeRTOS, uC/OS-II or uC-OS-III (non-free for commercial application). If nothing else, it simplifies communication between your "main loop" and ISRs. Anything I've done "bare metal" ends up with having a lot of work down in lower-prio ISRs that would really be better handled by another task. – Brian McFarland Feb 06 '15 at 14:58

2 Answers2

4

You could choose:

  • avoiding any kind of dynamic memory

  • implement your own malloc & free (or tune some existing malloc library for your need)

  • implement your own garbage collector (I guess that simple mark&sweep could be suitable in your case). Look e.g. into OpenMirage as an example showing that a GC-ed approach could make sense. Read the Gc HandBook for more.

  • use alloca (probably wrong)

  • use region or arena allocation techniques

BTW, the complexity of (e.g. cryptographic) algorithms is orthogonal to dynamic memory management....

Notice that you could e.g. customize your compiler chain (e.g. with MELT if using a recent GCC) to e.g. validate some specific coding rules related to your particular memory manager (or GC).

Basile Starynkevitch
  • 223,805
  • 18
  • 296
  • 547
  • 1
    GC is almost universally avoided in real-time systems, even in cases where `malloc` is allowed. Though to be fair, OP never stated any real-time constraints. – Brian McFarland Feb 06 '15 at 14:54
  • Again, a GC on 64Kbytes could be probably very fast (and fast-enough to be soft-real-time compatrible!), and a lot of C or C++ programs are reinventing GC techniques (e.g. refcounting). – Basile Starynkevitch Feb 06 '15 at 14:55
  • No, but I met several academics who told me they have tried with success.... My feeling is that the embedded software culture does not know well enough GC techniques (and still happen to use them without knowing ....) – Basile Starynkevitch Feb 06 '15 at 15:11
  • refcounting is common in embedded stuff, but never seen mark&sweep. May have to try it sometime. Also, keep in mind another big reason dynamic memory mgmt techniques are rare in embedded applications (on this scale) is "written in stone" rules in several industries prohibit / strongly discourage it and most developers follow those rules blindly (in spite of the fact that most have clauses to allow violating the rules). – Brian McFarland Feb 06 '15 at 15:30
  • Yes, I know that, but it is a pity (and a global massive loss of money & time). BTW, coding a good malloc is probably as hard as coding a good GC. – Basile Starynkevitch Feb 06 '15 at 15:39
2

It depends on the application you need to implement.

  1. As it has been mentioned in the comments, you can use global variables to store the data.

  2. However, if you actually need some dynamic memory allocation (you get the advantages of pointers and you can reallocate memory, which is useful in the case of some data structures, like linked lists or trees) you can implement your own memory allocator. Just use an array big enough with some meta-data about what is allocated an what is not allocated yet, and some functions that work like malloc and friends. It is not so complicated to create a good enough memory allocator, but you have to be careful with some errors that might occur. Also, you have to deal with memory fragmentation and all sorts of problems characteristic to memory allocation, but is feasible with a reasonable amount of effort.

  3. Also, you can create the whole data structure on the stack, but you lose some of the advantages of the dynamic memory allocation.

Paul92
  • 8,827
  • 1
  • 23
  • 37
  • RE #2: The reference `malloc` out of K&R is easy to adopt for this purpose. I've done this on applications where I know it's safe to blow away / reset the entire heap after a complex operation completes leaving it free from fragmentation next time through. – Brian McFarland Feb 06 '15 at 14:49
  • What do you mean "the advantage of pointers"? Pointers are not unique to dynamic memory allocation; you can take a pointer to any memory object. – Clifford Feb 06 '15 at 19:42
  • 1
    Yes, but unless you use dynamic memory allocation, you cannot allocate memory in a function and keep a pointer to it, because that memory will be deallocated from the stack when the function ends. But probably that wasn't the best way to describe this :D. – Paul92 Feb 06 '15 at 19:47