主机测试具有硬编码内存地址的 C 程序

Host testing C program with hard coded memory addresses

我们将为 C 代码编写 functional/unit 测试。此 C 程序将 运行 作为嵌入式软件。但是,我们需要在 Linux 环境中 运行 进行测试。

问题是部分被测代码如下所示:

my_addresses.h:

#define MY_BASE_ADDRESS     (0x00600000)
#define MY_OFFSET_ADDRESS   (0x108)

my_code.c

#include "my_addresses.h"

static const My_Type* my_ptr =
  (My_Type*)(MY_BASE_ADDRESS + MY_OFFSET_ADDRESS);

/* my_ptr is dereferenced and used ... */

显然,这在 Linux 主机环境中不会 运行 很好。

我们有什么办法可以在测试期间解决这个问题吗?我们能否以某种方式 "redirect" 程序使用其他地址,这些地址是在测试过程中分配的内存的有效地址?

我们的第一次尝试是在测试期间用另一个头文件替换 "my_addresses.h",它(外部)声明变量而不是硬定义 - 然后将 malloc 的内存分配给 MY_BASE_ADDRESS,等等。问题是 c 文件中的 "static const" 声明。当然你不能将变量分配给静态常量类型。

最好不要修改被测代码(尽管在最坏的情况下可能会变成那样)。

您可以检查例如__linux__ 宏并使用条件编译。启用时 Linux 使用数组作为基础,并使其足够大以在其中保存所有需要的数据。

例如

#ifdef __linux__
int8_t array[1024];
# define MY_BASE_ADDRESS array
#else
# define MY_BASE_ADDRESS 0x00600000
#endif

在Linux环境中你可以定义一个全局数组,然后使用它的地址作为你的基指针。

const char my_buffer[1024];
#define my_base_addr (&my_buff)

假设

  • 您的嵌入式内存布局足够小,可以在 Linux、
  • 上完全(或几个块)进行建模
  • 您的编译器对下面的常量内存地址表达式很满意,并且
  • My_Type 在您的示例中被定义为 typedef My_Type1_t * My_Type;

您可以 (1) 将嵌入式内存布局的定义与决定其放置方式分开,并且也许 (2) 如果您为布局声明 struct,则可以获得一些类型安全:

#pragma (essential: stuff to force structs to contain no extra padding)
typedef struct {
  char pad0[0x108];
  My_Type1_t foo;
  char pad1[0x210];
  My_Type2_t bar;
  ...
} Memory_Layout_t;
#pragma (preferably: something to revert to previous struct layout options)

(如果您不喜欢计算 pad1 的大小,请使用 union。)

然后制作变体:

#ifdef __linux__
Memory_Layout_t Embedded_Memory;
#  define Embedded_Memory_P (& Embedded_Memory)
#else
#  define Embedded_Memory_P ((Memory_Layout_t *) (0x00600000))
#endif

并用

引用它
static const My_Type my_ptr = & Embedded_Memory_P->foo;