如何在 MISRAC:2012 中创建遵循 Dir 4.12 和 4.8 的模块?

How do I create a module in MISRAC:2012 that follows Dir 4.12 and 4.8?

此问题与遵循 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();

这个问题中也描述了这个问题 Static allocation of opaque data types ,但未根据 MISRAC:2012 指南进行讨论。

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

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

我很好奇是否有一个广为接受的方法来解决这个问题,它满足 Dir 4.8 和 Dir 4.12,并且不违反任何其他 MISRAC:2012 规则。如有任何意见,我们将不胜感激。

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

不过这个池需要限制在一定的最大限制内,这应该是硬编码的。本质上,您将在文件范围内将池实现为 static 缓冲区,并使用计数器变量跟踪 "allocated" 大小。对于您添加的每个项目,您都会根据最大限制检查计数器。

如果您 运行 超出 space,您的程序会知道并能够以安全的方式处理该错误。不过,你 运行 出 space 永远不应该有理由。那将意味着您有一个设计错误。您几乎可以肯定能够确保在编译时不会 运行 超出 space。或者,如果不是,至少在代码覆盖率测试期间。


指令 4.12 关注 malloc/free 堆上的动态内存分配。使用这些函数和堆,是术语动态内存分配的 C 事实上标准定义。没有别的意思。

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

"dynamicness" 本身不是问题,只要程序行为保持确定性即可。安全标准总是关注堆上的动态内存分配,因为它暗示了非确定性行为,这是安全关键软件设计中的主要错误。

对于许多常见的嵌入式系统,例如 metal/RTOS 微控制器应用,dynamic allocation simply doesn't make any sense at all


所以静态内存池不是"dynamic memory allocation"。否则栈的使用也算"dynamic memory",根本写不出什么好用的软件