Domanda

I need some clarification about c++ memory management and MISRA guidelines..

I have to implement one program that it's MISRA compatible so I have to respect a important rule: is not possible to use 'new' operator (dynamic memory heap).

In this case, for any custom object, I must use static allocation:

For example:

I have my class Student with a constructor Student(int age). Whenever I have to instantiate a Student object I must do it this way:

int theAge = 18;
Student exampleOfStudent(theAge);

This creates an Student object exampleOfStudent. In this way I do not to have to worry about I do not use destructors. Is this correct all this? Are there other ways to use static memory management? Can I use in the same way std::vector or other data structure? Can I add, for example, a Student instance (that I created as Student exampleOfStudent(theAge)) into a std::vector.

È stato utile?

Soluzione

Student exampleOfStudent(theAge); is an automatic variable, not static.

As far as I remember, MISRA rules disallow all forms of dynamic memory. This includes both malloc and new and std::vector (with the default allocator).

You are left with only automatic variables and static variables.

If your system has a limited amount of RAM you don't want to use dynamic memory because of the risk you will ask for more memory than is available. Heap fragmentation is also an issue. This prevents you from writing provably correct code. If you use variables with automatic or static storage a static analysis application can, for instance, output the maximum amount of memory your application will use. This number you can check against your system RAM.

Altri suggerimenti

I once wrote a library that had to comply to the MISRA rules. I needed dynamic memory as well, so I came up with a trick:

My lib was written in C, but my trick may work for you.

Part of the header-file looked like this:

/* declare two function pointers compatible to malloc and free: */
typedef void * (*allocatorFunc)(size_t size);
typedef void   (*freeFunc)     (void * data);

/* and let the library user pass them during lib-init: */
int library_init (allocatorFunc allocator, freeFunc deallocator);

Inside the library I never called malloc/free directly. I always used the supplied function-pointers. So I delegated the problem how to the dynamic memory allocation should look like to someone else.

The customer actually liked this solution. He was aware of the fact that my library would not work without dynamic memory allocation and it gave him freedom to implement his own memory scheme using preallocated pools or whatnot.

In C++ you can do the same, just use the malloc function and do the object creation using placement new.

For MISRA compliance, placement-new is not a problem, as there is no dynamic allocation happening. A library could be written (like an STL allocator) in such a way as to reference a statically allocated memory region as it's memory pool for such a purpose. Advantages: deterministic, fast. Disadvantages: memory inefficient. A favorable trade off for deterministic real-time systems. All needed RAM has to be there at program startup, or the program won't run. If the program starts, it's unaffected by available heap size, fragmentation etc..

Writing ones own allocator can be complex and out-of-memory conditions (static memory pool size is fixed after all) still have to be dealt with.

The idea behind the rule is not that malloc and new, specifically, are unsafe, but that memory allocation is (usually) a lazy workaround for not understanding, or managing, the memory requirements of your program.

  • pre-allocating your calculated maximum input, and trapping overruns
  • providing a packet, stream, or other line-oriented means of managing input
  • use of an alternative pre-allocated data structure to manage non-uniform elements

Particularly in the context of a small, non-MMU, embedded system that lack of design depth frequently leads to an unstable system, that crashes outright in those odd, "corner case" exceptions. Small memory, short stack, is a system killer.

A few, of many, strategies that avoid the assumption that you do not have infinite memory, or even much memory in that inexpensive, embedded system - and force you to deal with the faults that might be important in your application.

Don't write your own malloc.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top