如何为基于ROM的程序预初始化内存数据结构?

3
考虑STL的unordered_map。同一模板类被用于在运行时生成的哈希表和由编译时常量值组成的哈希表。虽然C++的最新版本添加了constexpr支持,但它不扩展到涉及堆操作的更复杂操作。因此,从编译时常量构建哈希表仍必须在运行时完成,使得它与在运行时构建任何其他哈希表同样昂贵。
理想情况下,完美的编译器会看到这一点,并在编译时预先计算哈希表构造并将其直接嵌入程序中。
这让我想起复古计算和微控制器,它们可能会用C或C++编写软件,考虑到用汇编语言的开发成本:这些环境通常具有有限的RAM但有大量的ROM,并且那些内存数据结构(如unordered_map)肯定可以在编译时预先生成并持久化到ROM中。
如上所述,C++语言不支持非平凡constexpr进行此操作。我知道您可以把这些数据结构基于数组类型拼凑在一起,或者将它缩小到一个constexpr - 或者用汇编语言编写所有内容,并手动设置结构的每个字节到十六进制编辑器中,并希望它与编译器对您的struct类型的表示相匹配(例如)。
那么今天如何实现呢?在16位和32位游戏机的日子里,内存和CPU周期很昂贵。我特别想了解基于ROM卡带的游戏,其中这些结构立即作为原始内存可访问。

RAM比Flash和EEPROM快得多。通常,您希望将程序存储在Flash中,将持久数据存储在EEPROM中,将运行时数据存储在RAM中。 - Sid S
2
可能是通过不使用C++来完成的。 - user253751
3个回答

2

unordered_map 是一种非常低效的数据结构,你不会在这种情况下使用它。更合理的做法是使用静态初始化器来创建数组和树等数据结构。如果情况变得更加复杂,你可以编写一个程序来生成包含所需静态初始化器的 C 代码,并在能够处理它的系统上运行该程序。


2
unordered_map 在这种情况下为什么效率低下? - Jeremy Friesner
2
这是一个可变的哈希表,需要相当重的实现,并具有较大的运行时成本。如果您真的需要哈希表功能,编写不可变的哈希表以在原地使用非常简单。一个非常好的例子是对象文件和动态链接程序/库中使用的符号表。但对于您所询问的这种受限环境,最好根本不需要这种映射,而是在任何地方都使用指针/索引,而不是必须映射到地址的其他键。 - R.. GitHub STOP HELPING ICE

2
在C++微控制器系统中,具有静态存储期的对象的所有构造函数都会在引导期间调用,大约在初始化.data和.bss等段之前,并在调用main()之前。这是C ++往往不适合这种系统的几个原因之一 - 它实际上在启动阶段执行应用程序代码。
像旧视频游戏这样的应用程序通常会预先计算并写入ROM中的表格。我怀疑C ++在这样的游戏中并没有被广泛使用,或者如果使用了,则使用了语言的受限子集。

1
因此,我们经常看到由业余程序员或“PC程序员”编写的嵌入式C++代码,其中在MCU的基本硬件设置之前执行一些重型数据结构初始化代码(咳咳Arduino咳咳)。甚至在内部系统时钟初始化之前...然后他们上线到SO并对所有声称C比C ++快的人尖叫... - Lundin
不理解你的推理点。你在责怪语言而不是程序员所做的选举。语言为您提供了不同的机制,由您选择适合自己需求的机制。在C++中,您可以完美地定义常量编译时生成的数据,以在任何嵌入式系统的ROM中使用,就像问题所问的那样。如果您对静态对象初始化有问题(我怀疑它代表了一个普遍问题,而是一个具体情况的问题),只需使用其他机制即可。 - ronaldo

0

回到“古老的日子”——80年代和90年代初,RAM非常昂贵,闪存既昂贵又不可靠,但ROM,特别是掩模ROM很便宜。

视频游戏机通常使用ROM执行游戏,并使用少量RAM作为“刮板”内存。例如,原始的NES游戏机有2048字节的RAM。

编译语言在游戏开发中并不常用,因此回答您最初的问题,数据结构是通过将空结构从ROM复制到RAM来初始化的。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接