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

时间:2016-02-11 14:23:04

标签: c incomplete-type misra opaque-pointers

此问题与遵循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规则。任何评论将不胜感激。

1 个答案:

答案 0 :(得分:1)

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

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

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

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

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

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

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

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