此问题与遵循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规则。任何评论将不胜感激。
答案 0 :(得分:1)
您似乎已经理解了问题和解决方案:从每个ADT内部使用静态内存池。
这个池需要被限制到一定的最大限度,这应该是硬编码的。基本上,您将在文件范围内将池实现为static
缓冲区,并使用计数器变量跟踪“已分配”大小。对于您添加的每个项目,您将根据最大限制检查计数器。
如果您的空间不足,您的程序将知道它并能够以安全的方式处理该错误。永远不应该有你没有空间的原因。这意味着你有一个设计错误。您几乎肯定能够确保在编译时不会耗尽空间。或者如果没有,至少在代码覆盖测试期间。
指令4.12关注使用malloc/free
的堆上的动态内存分配。使用这些函数和堆,是术语动态内存分配的事实上的标准定义。这并不意味着什么。
动态分配存在多个问题:非确定性分配时间,分段,内存泄漏等。
“动态性”本身并不是一个问题,只要程序行为仍然是确定性的。安全标准总是关注堆上的动态内存分配,因为它意味着非确定性行为,这是安全关键软件设计中的一个主要原因。
对于许多常见的嵌入式系统,例如裸机/ RTOS微控制器应用,dynamic allocation simply doesn't make any sense at all。
因此静态内存池不是“动态内存分配”。否则,堆栈的使用将被视为“动态内存”,并且根本不可能编写任何有用的软件。