c - 没有功能指针的状态机

标签 c embedded state-machine misra safety-critical

我已经为安全sil 4系统实现了一个具有许多状态转换的复杂状态机。
此实现的后端是使用函数指针完成的。
当一切顺利进行时,v&v反对在sil 4系统中使用函数指针。参考-Rule 9 NASA.misra c 2004但是没有说不能使用函数指针。
有没有其他方法可以实现没有任何函数指针的复杂状态机?

最佳答案

首先,美国宇航局的文件不是佳能。首先询问强制你遵守nasa文件的法律/指令/标准/要求/文件。如果它没有在任何地方强制执行(这看起来很有可能,甚至在美国宇航局本身),你就没有义务遵循它,你可以忽略整个事情。
如果不能将这些废话视为废话,那么当你用安全标准撞墙时,你可以使用通常的程序:解决方案总是详细记录所述规则是如何不合理的,并用他们自己的方法扇他们耳光。
因此,与其放弃函数指针,不如通过下面描述的方法确保它们以安全的方式使用。
由于所有安全相关设计都归结为风险评估,因此您将始终:
错误->原因->危险->安全措施
根据美国宇航局文件中给出的(糟糕的)基本原理,你可以用如下方式证明安全措施“避免使用功能指针”:
执行错误代码->函数指针损坏->失控代码/非法操作代码
堆栈溢出->函数指针递归->内存损坏
混乱的程序员->函数指针语法->意外的程序功能
这都是相当模糊和可疑的风险评估,但这是美国宇航局的文件归结为。
对于上述3种危险,我建议使用以下安全措施,而不是“避免使用功能指针”:
防御性编程和断言。
防御性编程和断言。培养程序员。
使用typedef。培养程序员。
防御性编程和断言
对于状态机,请确保状态数(枚举中的项)对应于处理程序数(函数指针数组中的项)。只需静态断言枚举中的最后一个项(称为STATES_N或其他类似项)来反对sizeof(func_pointer_array)/sizeof(*func_pointer_array)
函数指针数组必须用错误检测/crc在rom中分配。其他安全要求将指向这一需求,最简单的解决方法是使用带有“ECC闪存”的微控制器。在ecc之前的日子里,你必须在整个rom上计算crc,这是复杂和乏味的,但也可以做到。您还可以创建表的相同rom镜像,以防止闪存损坏。
状态机代码允许调用的唯一函数指针是从这个安全函数指针数组中获取的指针。假设您的状态机调用看起来像STATE_MACHINE[i]();其中STATE_MACHINE是函数指针数组,那么只需添加i的运行时检查以确保它始终有效。
对于程序中的其他函数指针,例如回调函数,请确保将它们初始化为指向rom中的有效函数。如果可能,请使用const指针(指针本身是只读的)。如果需要在运行时重新分配它们,请确保它们在调用之前指向有效的函数。
上述类型的状态机是惯用的,非常安全,可能比代码中其他地方的普通函数调用要安全得多。当然,您必须确保以安全合理的方式完成状态传输,但这与函数指针无关。
避免递归
这主要是为了教育程序员不要使用它、函数指针或没有函数指针(似乎这可以防止toyota bug)。
它既不难发现也不避免递归,因此半正派的代码审查程序应该足以防止它。无论安全关键系统经验如何,经验丰富的嵌入式系统程序员都不会赞成包含递归的代码。
您可以/应该设置一个内部设计规则,规定所有安全相关代码必须由具有N年安全关键程序设计经验的资深C程序员审查和批准。
此外,还应该使用静态分析器工具检查递归(即使它们无法通过函数指针检测递归)。如果你有一个静态分析仪,符合任何版本的MISRA-C,这包括在内。
对于非预期递归,使用上述防御编程方法可以避免这种情况。
confusig函数指针语法
不可否认,C语言中的函数指针语法非常混乱,只需看看

int (*(*func)[5])(void);

或者其他一些荒谬的例子。它可以通过始终对函数指针类型强制typedef来解决。
(参考文献:Les Hatton,SAFER C,第184页,“从安全相关的观点来看,简单的答案是,不应允许它们出现在typedef机制之外。”)
有两种不同的类型定义它们,我更喜欢这样:
typedef int func_t (void);
func_t* fptr;

因为这不会隐藏typedef后面的指针,这通常是不好的做法。但如果你对另一种选择更满意
typedef int (*func_t) (void);
func_t fptr;

那也可以练习。

关于c - 没有功能指针的状态机,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34939379/

相关文章:

c - C 中的梯形积分

c - 使用计数排序的基数排序

finite-automata - 如何根据任意语言确定有限自动机的状态数?

UML 状态机图 - 并行进程

c - 是否有不支持可重入互斥锁或递归锁的平台?

ruby-on-rails - rails state_machine : How do I trigger an action on :initial state?

c++ - C 或 C++ 中的边界检查是否昂贵?

c - 如何在for循环中不按回车键填充数组

c++ - Microbit Platformio 开发 - 'PlatformIOLibBuilder' 对象没有属性 'get_inc_dirs'

c - TI MSP430 中断源