调整 struct / char 数组的大小(以减少内存使用)

Resizing struct / char array (to reduce memory usage)

这是我在 Arduino/C++/ESP32 上的第一个项目。我写了一个相当大的程序,几乎所有的东西都能正常工作——除了最后我意识到设备会 运行 周期性地喘不过气来(内存)并重新启动。重新启动是因为我配置了一个看门狗来这样做。

有一个领域我认为有机会减少内存使用,但我在 c++ 上的经验是 "not there yet" 让我能够自己编写它。请问有什么指点(没有双关语)吗?我从昨天开始就一直在处理这个问题,摆脱一个错误只会导致另一个新错误出现。此外,我不想想出一些 hacky 或以后可能会崩溃的东西。对于这里有经验的人来说,这应该是一个快速的答案。

让我解释一下我更喜欢的代码 refactor/optimize。

我需要存储一堆记录,以后 read/manipulate 需要这些记录。我在全局声明了一个结构(因为它们是相关字段)。现在的问题是我可能需要存储 1 条记录、2 条记录或 5 条记录,这些记录只有在我从 EEPROM 读取数据后才能知道。这必须是所有函数都可以访问的,所以它必须是一个全局声明。

总结

问题 1 - 一旦从 eeprom 读取数据,如何在程序后面设置“NumOfrecs”。

问题 2 - char 数组用户名的大小 (sizeOfUsername) 也可以根据从 eeprom 读取的用户名的长度而改变。有时它可能是 5 个字符长,有时它可能是 25 个。我可以将它设置为最多 25 个并解决这个问题,但是如果许多用户名只有 4-5 个字符长,我会不会浪费内存?所以简而言之 - 在将 eeprom 中的数据复制到 "username" char 数组之前,是否可以将其大小设置为保存该数据所需的最佳大小(即数据大小 + 1 个字节以用于空终止).

struct stUSRREC {
  char username[sizeOfUsername];
  bool online;
}; 

stUSRREC userRecords[NumOfrecs];

我熟悉了一大堆函数,如 strcpy、memset、malloc 等,但现在 运行 没时间了,需要把学习部分改天再说。

我可以尝试以稍微不同的方式执行此操作,我不使用结构而是使用单独的字符数组(对于每个字段,如用户名)。但是话又说回来,当我从 eeprom 读取数据时,我将不得不调整数组的大小。

我可以解释我尝试过的所有事情,但这会使这个问题变得不必要地冗长,并且可能导致失去一些清晰度。非常感谢任何帮助。

在回答关于 SO 的问答时,我尝试了一些随机的东西,至少下面的这段代码似乎有效(就存储 smaller/bigger 值而言)

struct stUSRREC {
  char username[];        
  bool online;                   
}; 

stUSRREC userRecords[5];

然后这样操作

strcpy(userRecords[0].username, "MYUSERNAME");
strcpy(userRecords[0].username, "test");
strcpy(userRecords[0].username, "MYVERYBIGUSERNAME");

我已经能够 write/rewrite 不同的长度(以上)并且可以正确地读回所有这些。调整大小 "userRecords" 可能是另一场比赛,但可以稍等片刻

有一件事我忘了提,我只需要 size/resize 数组(包含用户名)一次。在 setup() 本身中,我可以 read/load 将所需的数据放入这些数组中。我不确定这是否会带来任何其他可能性。在 运行 期间我需要操作的其余 struct/array 只是布尔值和整数值。这根本不是问题,因为这样做不需要调整大小。

附带说明一下,我很确定我不是唯一遇到这种情况的人。任何 tips/clues/pointers 都可能对其他许多人有所帮助。当你真正开始为它们加载一堆东西时,对像 ESP32 这样的小设备的限制就会变得更加明显。我用 "Strings"(大写字母 S)完成了所有工作,但定期重启(cpu 饥饿?)要求我摆脱字符串。即便如此,我听说使用字符串(在 ESP、Arduino 和帮派上)是个坏主意。

你把这个问题标记为 C++,所以我会问:

您可以在嵌入式代码中使用 vectorstring 吗?

#include <string>
#include <vector>

struct stUSRREC {
  std::string username;
  bool online;
  stUSRREC(const char* name, bool isOnline) :
       username(name), 
       online(isOnline)
  {
  }
};

std::vector<stUSRREC> userRecords;

使用 string 作为用户名类型意味着您只需分配保存名称所需的字符数,而不是分配假定的最大大小 sizeOfUsernamevector 的使用允许您动态地增加记录集。

然后添加一条新记录:

stUSRREC record("bob", true);
userRecords.push_back(record);

您可能不再需要 NumOfrecsuserRecrods.size()

涵盖了这些内容