在C语言中,在小型嵌入式系统上,有什么理由不执行以下操作?
const char * filter_something(const char * original, const int max_length)
{
static char buffer[BUFFER_SIZE];
// Checking inputs for safety omitted
// Copy input to buffer here with appropriate filtering, etc.
return buffer;
}
Run Code Online (Sandbox Code Playgroud)
这本质上是一个实用函数,源是可能已损坏的闪存,我们进行一种“安全复制”以确保我们有一个以空结尾的字符串。我选择使用静态缓冲区并使其对调用者只读。
一位同事告诉我,我这样做在某种程度上不尊重缓冲区的范围,对我来说,这对于我们拥有的用例来说非常有意义。
有理由不这样做吗?
非常感谢所有回复的人。您基本上证实了我对此的想法,对此我深表感谢。我一直在寻找不这样做的主要原因,但我认为没有。澄清几点:
租用/线程安全不是问题。它是一个具有单个运行循环的小型(裸机)嵌入式系统。该代码永远不会从 ISR 中调用。
在这个系统中,我们并不缺乏内存,但我们确实想要非常可预测的行为。出于这个原因,我更喜欢静态地声明这样的对象,尽管它可能有点“浪费”。我们已经遇到了在堆栈上不小心声明的大对象的问题,这导致间歇性崩溃(现已修复,但需要一段时间才能诊断)。所以总的来说,我更喜欢静态分配,只是为了具有非常可预测性、可靠性和下游潜在问题较少。
所以基本上这是针对特定系统设计采取某种方法的情况。
我写了一个 python 3 脚本来测试到 FPGA 的 SPI 链接。它在 Raspberry Pi 3 上运行。测试的工作方式如下:将 FPGA 置于测试模式(一个按钮开关)后,发送第一个字节,该字节可以是任何值。然后无限期发送更多字节。每一个都增加发送的第一个值,截断为 8 位。因此,如果第一个值为 37,则 FPGA 需要以下序列:
37, 74, 111, 148, 185, 222, 4, 41 ...
一些额外的 IO 引脚用于在设备之间发送信号 - RUN(RPi 输出)开始测试(这是必要的,因为如果 FPGA 需要一个字节,它会在大约 15ms 内超时)并且 ERR(FPGA 输出)发出错误信号。因此可以在两端计算错误。
此外,RPi 脚本会在每百万字节中写入一行发送的字节数和错误数的摘要。
所有这些都很好。但是运行大约3天后,我在RPi上收到以下错误:
free(): 无效指针: 0x00405340
我在两个相同的测试设置上得到完全相同的错误,即使是相同的内存地址。最后一个报告说“发送了 4294M 字节,0 个错误”
我似乎已经证明了 SPI 链接,但我担心这个长时间运行的程序会无缘无故地崩溃。
这是我的测试代码的重要部分:
def _report(self, msg):
now = datetime.datetime.now()
os.system("echo \"{} : {}\" > spitest_last.log".format(now, msg))
def spi_test(self):
global end_loop
input("Put the FPGA board into SPI test mode (SW1) …Run Code Online (Sandbox Code Playgroud)