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
因为小型内存受限嵌入式系统上的动态内存分配很难管理。
我有各种不同的 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
因为小型内存受限嵌入式系统上的动态内存分配很难管理。