C(avr-gcc 是带有 类 和 new/delete 的 C)- 不为微控制器上的非实例化 类 分配内存的最佳方式

C (avr-gcc is C with classes and new/delete) - Best way to not allocate memory for non-instatiated classes on microcontroller

我有各种不同的 PCB,每个 PCB 都有一个使用 avr-gcc/ C 编译器的 AtMega2560 微控制器(使用 Arduino 1.8.12 编译器,它有 类、new、delete 但不是 vector 和这样的)。我的固件对于所有 PCB 都是相同的,这非常好,因为单个 EEPROM 字节允许 PCB select 它的类型,并且所有 PCB 使用相同的固件 运行。但是我有内存问题,不想为非实例化 类 分配内存。例如,2 种不同类型的 PCB 可能有大型数组,对不同的信息进行不同的分配:

voltateOutputPcb.h:
Class voltateOutputPcb
     uint8_t outputVoltages[1000];

temperaturePCB.h:
Class temperaturePCB
     uint32_t temperatureSensorReading[200];

用法很漂亮。获取第 100 个(0 索引)outputVoltages_array 元素:

uint8_t 100thSensorValue = outputVoltages[100];

选项 #1:在构造期间使用指针分配内存

如果select这两个类的代码使用了#include,那么两个大数组在编译时都分配在堆栈上。我只想分配实际要实例化的内存。一种方法是分配一个指针并在构造函数中使用 new 创建数组:

voltageOutputPcb.h:
Class voltateOutputPcb
     uint8_t *outputVoltages_array;

voltageOutputPcb.cpp constructor:
outputVoltages_array = new uint8_t[1000];

但是用法有点难看,可能会导致未来的错误。获取第 100 个 outputVoltages_array 元素:

uint8_t 100thSensorValue = *(outputVoltages_array+100);

选项 #2:代码的单独版本

另一种选择是制作不同的固件编译版本,以便每个 PCB 都只包含它需要的 .h 文件#included。这将是进行多次编译并保存每个不同输出文件的手动过程。这也不理想,因为拥有 1 段代码真的很好,在 select 时间 select 编辑了细节。

选项 #3:共享内存

拥有一个在不同实例之间以不同方式分配的大内存 space 是一种选择......但在这里不是一个很好的选择,因为内存被用于非常不同的事情。在这种情况下,我觉得这远不如上面的选项#1。

有没有更好的方法?

有没有更好的方法在构造时动态分配内存?是否有更少的手动方式来有条件地 #include 仅我想要的内容?

其他一些相关链接:

Forward Declaration vs Include

Regarding C++ Include another class

Including .cpp files

Static array vs. dynamic array in C++

我会考虑 union。类似于:

struct PcbCommon
{
    char pcbName[32];
    unsigned version;
    char sn[200];
    uint8_t some_big_common_array[100];
    ...
};

struct PcbA
{
    uint8_t some_big_array_specific_to_PCB_A[1000];
    ...
}

struct PcbB
{
    uint8_t some_big_array_specific_to_PCB_B[500];
    ...
}

struct Pcb
{
    struct PcbCommon common;
    union
    {
        struct PcbA pcbA;
        struct PcbB pcbB;
        ...
    } u;
};

通过这种方式,您分配的内存永远不会超过您最 memory-demanding PCB 的需要。事实上,你总是会分配最 memory-demanding PCB 需要的东西,但既然你必须“处理”那个 PCB,那应该不是问题。

p.s。我会避免 new/delete 因为小型内存受限嵌入式系统上的动态内存分配很难管理。