Is realloc() safe in embedded system?
Asked Answered
T

6

10

While developing a piece of software for embedded system I used realloc() function many times. Now I've been said that I "should not use realloc() in embedded" without any explanation.

Is realloc() dangerous for embedded system and why?

Trainload answered 25/8, 2011 at 9:31 Comment(6)
Why don't you ask whoever told you so ?Noel
Embedded is a very very broad area these days.Solitaire
@Noel if i could ask them then i will never ask this here..!!Trainload
@Mr.32 I was implying that you shouldn't accept opinions without arguments.Noel
@Noel ya in that way you are right. I have argued with them but they have just said realloc is dangerous to embedded so dont use.i m just developer so i have to follow them..!Trainload
Specifically realloc() and not malloc() or alloca()? I think I remember seeing realloc() criticised in a book because of its highly overloaded behaviour, once, but I don't really go along with that, and I'd be disappointed if anybody saw fit to prohibit it on those grounds.Kendall
I
21

Yes, all dynamic memory allocation is regarded as dangerous, and it is banned from most "high integrity" embedded systems, such as industrial/automotive/aerospace/med-tech etc etc. The answer to your question depends on what sort of embedded system you are doing.

The reasons it's banned from high integrity embedded systems is not only the potential memory leaks, but also a lot of dangerous undefined/unspecified/impl.defined behavior asociated with those functions.

EDIT: I also forgot to mention heap fragmentation, which is another danger. In addition, MISRA-C also mentions "data inconsistency, memory exhaustion, non-deterministic behaviour" as reasons why it shouldn't be used. The former two seem rather subjective, but non-deterministic behaviour is definitely something that isn't allowed in these kind of systems.

References:

  • MISRA-C:2004 Rule 20.4 "Dynamic heap memory allocation shall not be used."
  • IEC 61508 Functional safety, 61508-3 Annex B (normative) Table B1, >SIL1: "No dynamic objects", "No dynamic variables".
Industrialize answered 25/8, 2011 at 9:43 Comment(12)
This is the only good answer. You should never use heap memory in embedded systems. Place all data in the data section, bss or on the stack. This way you have a fixed size memory footprint and you can calculate your memory usage. This way you know for sure how much memory you are actually using and you can never exceed that limit. Using heap is the most common vector in making embedded systems crash after running for a longer period of time.Fotinas
I understood the question as related to realloc() in particular, not about using dynamic memory allocation or not.Mediacy
@Fotinas - Is that using heap causes crash? or invalid usage of heap cause crash? feel the difference.. you can crash much easier - by wrongly using pointers.. - should we disable pointers?Mediacy
@DipSwitch: Now that we have "embedded systems" with 64 megs or even a half gigabyte of RAM, "never" no longer applies.Bronchitis
@Mediacy The question was whether realloc() is dangerous or not. The answer is, yes it is, just as any form of dynamic memory allocation.Industrialize
It's not quite true that you should "never" use the heap in embedded systems, but you must prove (based on your program and the implementation's allocator) that fragmentation and memory use remain bounded so that an allocation will never fail. This is usually nearly impossible, but one simple way is to have a fixed allocation pattern at startup and no further allocations. There are other easy cases too, like if the heap is normally unused except for one operation that performs many allocations followed immediately by the corresponding frees.Semiskilled
If one calls malloc() at startup and then never call free() then the problem with memory fragmentation never occurs. Also note that realloc() is significantly more complicated than malloc(). See for exampe Steve Maguire's book "Writing Solid Code" where he devotes a several pages with criticism of realloc().Systematism
@Systematism If you call malloc at startup and never again, why didn't you allocate the memory statically in the first place?Industrialize
@Lundin: At compile-time you may not have needed information about the size of objects or the number of objects to allocate. Such information may be stored on Flash or SD-card (e.g. as a configuration file).Systematism
@Systematism That doesn't matter. You would still obviously have to reserve heap size for the largest amount of memory you will ever encounter in the flash. So you could allocate a heap or a static array, there is no difference, except for the former being slower and unsafer. A heap is only meaningful if you need to allocate memory during runtime.Industrialize
Using dynamic memory allocation may provide for cleaner code. You can also use libraries which allocates memory dynamically.Systematism
@Lundin: One real-world scenario where I used a heap-like allocation was an embedded system which was supposed to hold as much data in RAM as would fit. If I had compile-time allocated the storage, then I would either have to define my static size to a value that was needlessly small, or else shrink my compile-time allocation any time I added something else which would statically allocate some more RAM). As it was, I set my linker spec to force one variable to go just after the highest static allocation, and force another variable to the end of RAM. The space between them became my heap.Thorin
B
5

It depends on the particular embedded system. Dynamic memory management on an small embedded system is tricky to begin with, but realloc is no more complicated than a free and malloc (of course, that's not what it does). On some embedded systems you'd never dream of calling malloc in the first place. On other embedded systems, you almost pretend it's a desktop.

If your embedded system has a poor allocator or not much RAM, then realloc might cause fragmentation problems. Which is why you avoid malloc too, cause it causes the same problems.

The other reason is that some embedded systems must be high reliability, and malloc / realloc can return NULL. In these situations, all memory is allocated statically.

Bronchitis answered 25/8, 2011 at 9:35 Comment(2)
I'm not an embedded guy, but you seem to be going off on tangents about free and malloc. Realloc is potentially lot more than that, it's just that the interface is simple.Sashasashay
I was saying that it was not more complicated than malloc and free, not that it was somehow composed of them. I'm sorry if my imprecise wording merits your disapproval.Bronchitis
T
4

In many embedded systems, a custom memory manager can provide better semantics than are available with malloc/realloc/free. Some applications, for example, can get by with a simple mark-and-release allocator. Keep a pointer to the start of not-yet-allocated memory, allocate things by moving the pointer upward, and jettison them by moving the pointer below them. That won't work if it's necessary to jettison some things while keeping other things that were allocated after them, but in situations where that isn't necessary the mark-and-release allocator is cheaper than any other allocation method. In some cases where the mark-and-release allocator isn't quite good enough, it may be helpful to allocate some things from the start of the heap and other things from the end of the heap; one may free up the things allocated from one end without affecting those allocated from the other.

Another approach that can sometimes be useful in non-multitasking or cooperative-multitasking systems is to use memory handles rather than direct pointers. In a typical handle-based system, there's a table of all allocated objects, built at the top of memory working downward, and objects themselves are allocated from the bottom up. Each allocated object in memory holds either a reference to the table slot that references it (if live) or else an indication of its size (if dead). The table entry for each object will hold the object's size as well as a pointer to the object in memory. Objects may be allocated by simply finding a free table slot (easy, since table slots are all fixed size), storing the address of the object's table slot at the start of free memory, storing the object itself just beyond that, and updating the start of free memory to point just past the object. Objects may be freed by replacing the back-reference with a length indication, and freeing the object in the table. If an allocation would fail, relocate all live objects starting at the top of memory, overwriting any dead objects, and updating the object table to point to their new addresses.

The performance of this approach is non-deterministic, but fragmentation is not a problem. Further, it may be possible in some cooperative multitasking systems to perform garbage collection "in the background"; provided that the garbage collector can complete a pass in the time it takes to chug through the slack space, long waits can be avoided. Further, some fairly simple "generational" logic may be used to improve average-case performance at the expense of worst-case performance.

Thorin answered 26/8, 2011 at 21:40 Comment(0)
J
2
  1. realloc can fail, just like malloc can. This is one reason why you probably should not use either in an embedded system.

  2. realloc is worse than malloc in that you will need to have the old and new pointers valid during the realloc. In other words, you will need 2X the memory space of the original malloc, plus any additional amount (assuming realloc is increasing the buffer size).

  3. Using realloc is going to be very dangerous, because it may return a new pointer to your memory location. This means:

    • All references to the old pointer must be corrected after realloc.
    • For a multi-threaded system, the realloc must be atomic. If you are disabling interrupts to achieve this, the realloc time might be long enough to cause a hardware reset by the watchdog.

Update: I just wanted to make it clear. I'm not saying that realloc is worse than implementing realloc using a malloc/free. That would be just as bad. If you can do a single malloc and free, without resizing, it's slightly better, yet still dangerous.

Jilly answered 25/8, 2011 at 10:8 Comment(3)
Wouldn't points 2 and 3 apply to manually calling malloc()/free()?L
3. is a good point, realloc is indeed more dangerous than malloc for that reason, even though malloc alone is considered too dangerous to begin with.Industrialize
@L - Right, realloc is just doing malloc/free in some cases. So my answer tries to explain that realloc is not magic, and dangerous. It may not be clear where the dragons are, unless one implements realloc using malloc/free API. I just wanted to directly call out the memory overhead.Jilly
A
1

The issues with realloc() in embedded systems are no different than in any other system, but the consequences may be more severe in systems where memory is more constrained, and the sonsequences of failure less acceptable.

One problem not mentioned so far is that realloc() (and any other dynamic memory operation for that matter) is non-deterministic; that is it's execution time is variable and unpredictable. Many embedded systems are also real-time systems, and in such systems, non-deterministic behaviour is unacceptable.

Another issue is that of thread-safety. Check your library's documantation to see if your library is thread-safe for dynamic memory allocation. Generally if it is, you will need to implement mutex stubs to integrate it with your particular thread library or RTOS.

Not all emebdded systems are alike; if your embedded system is not real-time (or the process/task/thread in question is not real-time, and is independent of the real-time elements), and you have large amounts of memory unused, or virtual memory capabilities, then the use of realloc() may be acceptable, if perhaps ill-advised in most cases.

Rather than accept "conventional wisdom" and bar dynamic memory regardless, you should understand your system requirements, and the behaviour of dynamic memory functions and make an appropriate decision. That said, if you are building code for reuability and portability to as wide a range of platforms and applications as possible, then reallocation is probably a really bad idea. Don't hide it in a library for example.

Note too that the same problem exists with C++ STL container classes that dynamically reallocate and copy data when the container capacity is increased.

Animality answered 26/8, 2011 at 21:9 Comment(0)
M
0

Well, it's better to avoid using realloc if it's possible, since this operation is costly especially being put into the loop: for example, if some allocated memory needs to be extended and there no gap between after current block and the next allocated block - this operation is almost equals: malloc + memcopy + free.

Mediacy answered 25/8, 2011 at 9:49 Comment(4)
Is realloc() any worse than malloc()/free()?L
Worse because reallocation may be optimized by using adjacent memory blocks, but this of course not always possibleMediacy
@pmod: An individual call to realloc should never be worse than malloc / memcpy / free, because it could always just do that, and it might obviate the memcpy.Bronchitis
Sorry for messing up with negation, all I meant "at least it's not worse, but statistically even better" which depends on implementationMediacy

© 2022 - 2024 — McMap. All rights reserved.