1

我必须说,我在一个看似基本的问题上遇到了相当大的难题。我有一个结构,我想将一个数组存储为一个字段。我想在不同的上下文中重用这个结构,有时我需要一个更大的数组,有时需要一个更小的数组。C 禁止使用可变大小的缓冲区。因此,自然的方法是将指向该数组的指针声明为结构成员:

struct my {
    struct other* array;
}

然而,这种方法的问题是我必须遵守 MISRA-C 的规则,它禁止动态内存分配。那么,如果我想分配内存并初始化数组,我不得不这样做:

var.array = malloc(n * sizeof(...));

这是 MISRA 标准所禁止的。我还能怎么做?

4

3 回答 3

2

由于您遵循 MISRA-C,我猜该软件在某种程度上是关键任务,在这种情况下,所有内存分配都必须是确定性的。每个安全标准都禁止堆分配,不仅是 MISRA-C,还有更通用的安全标准(IEC 61508、ISO 26262、DO-178 等)。

在这样的系统中,您必须始终针对最坏的情况进行设计,这将消耗最多的内存。您需要准确分配那么多空间,不多也不少。在这样的系统中,其他一切都没有意义。

鉴于这些先决条件,您必须分配一个 size 的静态缓冲区LARGE_ENOUGH_FOR_WORST_CASE。一旦你意识到这一点,你只需要找到一种方法来跟踪你在这个缓冲区中存储了什么样的数据,方法是使用一个枚举,也许还有一个“使用的大小”计数器。


请注意,MISRA-C:2012 不仅禁止 malloc/calloc,还禁止 VLA 和灵活数组成员。如果您使用的是 C90/MISRA-C:2004,则没有 VLA,也没有任何明确定义的灵活数组成员的使用——它们在 C99 之前调用了未定义的行为。

于 2015-04-08T11:08:56.607 回答
0

编辑:此解决方案不符合 MISRA-C 规则。

您可以在结构定义包含 VLA,但前提是它位于函数内部。解决此问题的一种方法是在主结构的末尾使用“灵活数组成员”,如下所示:

#include <stdio.h>
struct my {
  int len;
  int array[];
};

您可以创建对该结构进行操作的函数。

void print_my(struct my *my) {
  int i;
  for (i = 0; i < my->len; i++) {
    printf("%d\n", my->array[i]);
  }
}

然后,要创建此结构的可变长度版本,您可以在函数体中创建一种新类型的结构,其中包含您的my结构,但也定义该缓冲区的长度。这可以通过不同的大小参数来完成。然后,对于您调用的所有函数,您只需传递一个指向包含struct my值的指针,它们就会正常工作。

void create_and_use_my(int nelements) {
  int i;

  // Declare the containing struct with variable number of elements.
  struct {
    struct my my;
    int array[nelements];
  } my_wrapper;

  // Initialize the values in the struct.
  my_wrapper.my.len = nelements;
  for (i = 0; i < nelements; i++) {
    my_wrapper.my.array[i] = i;
  }

  // Print the struct using the generic function above.
  print_my(&my_wrapper.my);
}

您可以使用任何值调用此函数,nelements它会正常工作。这需要 C99,因为它确实使用 VLA。此外,还有一些GCC 扩展使这更容易一些。

重要提示:如果您将 传递struct my给另一个函数,而不是指向它的指针,我几乎可以保证它会导致各种错误,因为它不会复制可变长度数组。

于 2015-04-07T14:39:08.703 回答
0

这是一个可能完全不适合您的情况的想法,但是鉴于您的限制,我不确定如何处理它。

创建一个大型静态数组并将其用作您的“堆”:

static struct other heap[SOME_BIG_NUMBER];

然后,您将从这个“堆”中“分配”内存,如下所示:

var.array = &heap[start_point];

您必须做一些簿记来跟踪您的“堆”的哪些部分已被分配。这假设您对可执行文件的大小没有任何主要限制。

于 2015-04-07T14:41:37.710 回答