问题描述
我有各种不同的PCB,每个PCB都带有一个使用avr-gcc / C编译器的AtMega2560微控制器(使用Arduino 1.8.12编译器,该类具有new,delete但没有vector等类)。我的固件对于所有PCB都是相同的,这非常好,因为单个EEPROM字节允许PCB选择其类型,并且所有PCB都可以使用相同的固件运行。但是我遇到了内存问题,并且不想为非实例化的类分配内存。例如,两种不同类型的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:在构建期间使用指针分配内存
如果选择这两个类的代码都使用#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文件。这将是一个手动过程,需要进行多次编译并保存每个不同的输出文件。这也不是理想的选择,因为只有一段代码并在运行时选择详细信息真是太好了。
选项3:共享内存
有一个大的内存空间可以在不同的实例之间分配,这是一个选择……但是在这里不是一个很好的选择,因为内存用于不同的事物。在这种情况下,我觉得这不如上面的选择1。
有更好的方法吗?
是否有更好的方法在构造上动态分配内存?是否有较少的手动方式来有条件地仅包含我想要的内容?
其他一些相关链接:
Forward Declaration vs Include
Regarding C++ Include another class
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;
};
这样,您分配的内存将永远不会超过最需要内存的PCB需求。实际上,您将始终分配最需要内存的PCB所需的资源,但是您必须“处理”该PCB,这不成问题。
p.s。我会避免使用new/delete
,因为在受内存限制的小型嵌入式系统上很难动态分配内存。