如何在DIS 4.12和4.8之后的MISRAC:2012中创建模块?

该问题涉及遵循MISRAC:2012指南的ISO C99编码。

我正在寻找关于Dir 4.8的指导“如果在翻译单元中从不取消引用结构或联合的指针,那么应该隐藏对象的实现”与Dir 4.12一起“不应使用动态内存分配”。

在C中实现抽象数据类型时,通常使用句柄来引用ADT,该句柄是指向描述ADT内部状态的结构的指针。 这可以使用根据Dir 4.8的不透明指针来完成,其好处是内部细节对用户隐藏。

通常可以存在多个这些ADT,因此必须有一种方法来创建多个句柄。 这可以通过在初始化函数中为句柄引用的内部细节分配内存来解决,但是,在Dir 4.12下不允许这样做。

另一个选择是初始化例程接收指向用户提供的静态分配句柄的指针,但是,这不能使用不透明指针来完成。

我在下面说明了这个问题。

Module.h struct module; typedef struct module module_t; /* Module handle is only available to the world as an incomplete type. This allows us to satisfy MISRAC 2012 Dir 4.8.*/ Module.c #include "module.h" struct module { uint8_t value; }; module_t* module_get_a_handle(void) { return (module_t*)malloc(sizeof(struct module)); /* MISRAC 2012 Dir 4.12 disallows dynamic memory allocation.*/ } User.c #include "module.h" module_t* module_handle; module_handle = module_get_a_handle(); 

该问题还在此问题中描述了不透明数据类型的静态分配 ,但是没有针对MISRAC:2012指南进行讨论。

描述的一种解决方案是使用静态分配的句柄池,这些句柄可用于客户端代码。 这个解决方案似乎在技术上是合规的; 但是,似乎动态内存分配的概念仍然存在于此。 我认为虽然句柄是静态分配的,但编译期间编译器无法确定是否有足够的句柄可供软件正常运行。

我对这个问题的解决方案是在Dir 4.8周围编写一个偏差,并使用非不透明指针和强大的命名约定,使用户明白不得更改ADT的内部细节。

我很好奇是否有一个公认的方法来解决满足Dir 4.8和Dir 4.12的问题,并且不会破坏任何其他MISRAC:2012规则。 任何评论将不胜感激。

您似乎已经理解了问题和解决方案:从每个ADT内部使用静态内存池。

这个池需要被限制到一定的最大限度,应该是硬编码的。 实际上,您将在文件范围内将池实现为static缓冲区,并使用计数器变量跟踪“已分配”大小。 对于您添加的每个项目,您将根据最大限制检查计数器。

如果您的空间不足,您的程序将知道它并能够以安全的方式处理该错误。 永远不应该有你没有空间的原因。 这意味着你有一个设计错误。 您几乎肯定能够确保在编译时不会耗尽空间。 或者如果不是,至少在代码覆盖测试期间。


指令4.12关注具有malloc/free的堆上的动态内存分配。 使用这些函数和堆,是术语动态内存分配的事实上的标准定义。 这并不意味着什么。

动态分配存在多个问题:非确定性分配时间,分段,内存泄漏等。

只要程序行为仍然是确定性的,“动态性”本身并不是一个问题。 安全标准始终关注堆上的动态内存分配,因为它意味着非确定性行为,这是安全关键软件设计中的一个主要原因。

对于许多常见的嵌入式系统,例如裸机/ RTOS微控制器应用, 动态分配根本没有任何意义 。


所以静态内存池不是“动态内存分配”。 否则,堆栈的使用将被视为“动态内存”,并且根本不可能编写任何有用的软件。