简体   繁体   English

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

[英]Resizing struct / char array (to reduce memory usage)

This is my first project on Arduino/C++/ESP32. 这是我在Arduino / C ++ / ESP32上的第一个项目。 I wrote a fairly big program and got almost everything working - except that in the end I realized that the device would run out of breath (memory) periodically and go for a reboot. 我写了一个相当大的程序,几乎所有东西都可以工作-到最后,我意识到设备会周期性地耗尽呼吸(内存)并重新启动。 The reboot is because I configured a watchdog to do so. 重新启动是因为我配置了监视程序来执行此操作。

There is one area where I think there's a chance to reduce the memory usage but my experience on c++ is "not there yet" for me to be able to write this by myself. 我认为有一个地方可以减少内存使用量,但是我对c ++的经验“还不存在”,我可以自己编写。 Any pointers (no pun intended) please? 请问任何指针(无双关语)? I have been on this since yesterday and getting rid of one error only results in another new error popping up. 从昨天开始,我一直在研究这个问题,而摆脱一个错误只会导致弹出另一个新错误。 Moreover I don't want to come up with something that is hacky or might break later. 而且,我不想提出一些有问题的东西或以后可能会损坏的东西。 It should be a quick answer for the experienced people here. 对于这里有经验的人来说,这应该是一个快速的答案。

Let me explain the code that I prefer to refactor/optimize. 让我解释一下我更喜欢重构/优化的代码。

I need to store a bunch of records that I would need to read/manipulate later. 我需要存储一堆记录,以后需要阅读/操作。 I declared a struct ( because they are related fields ) globally. 我全局声明了一个struct( 因为它们是相关字段 )。 Now the issue is that I may need to store 1 record, 2 records or 5 records which I would only know later once I read the data from the EEPROM. 现在的问题是,我可能需要存储1条记录,2条记录或5条记录,这些信息只有在我从EEPROM中读取数据后才会知道。 And this has to be accessible to all the functions so it has to be a global declaration. 而且所有功能都必须可以访问它,因此它必须是全局声明。

To summarize 总结一下

Question 1 - how to set " NumOfrecs " later in the program once the data is read from the eeprom. 问题1-从eeprom中读取数据后,如何在程序的后面设置“ NumOfrecs ”。

Question 2 - The size( sizeOfUsername ) of the char array username can also change depending upon the length of the username read from the eeprom. 问题2 -char数组用户名的大小( sizeOfUsername )也可以根据从eeprom中读取的用户名的长度进行更改。 At times it might be 5 characters long, at times it could be 25. I can set it to a max 25 and solve this problem but then wouldn't I be wasting memory if many usernames were just 4-5 characters long? 有时它的长度可能是5个字符,有时可能是25个字符。我可以将其设置为最大25个字符并解决此问题,但是如果许多用户名长度只有4-5个字符,我是否会浪费内存? So in short - just before copying over the data in eeprom into the "username" char array, is it possible to set it's size to the optimal size required for holding that data ( which is the data size + 1 byte for null termination ). 简而言之-在将eeprom中的数据复制到“用户名” char数组之前,可以将其大小设置为保存该数据所需的最佳大小(这是数据大小+空终止的1个字节)。

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

stUSRREC userRecords[NumOfrecs];

I familiarized myself with a whole bunch of functions like strcpy, memset, malloc etc but now I have run out of time and need to keep the learning part for another day. 我使自己熟悉了诸如strcpy,memset,malloc等一整套函数,但是现在我已经用光了时间,需要继续学习另一天。

I can try to do this in a slightly different manner where I don't use the struct and instead use individual char arrays ( for each field like username ). 我可以尝试以一种略有不同的方式执行此操作,在这种方式中,我不使用该结构,而是使用单独的char数组(对于每个字段,如username)。 But then again I'll have to resize the arrays as I read the data from the eeprom. 但是话又说回来,当我从eeprom中读取数据时,我将不得不调整数组的大小。

I can explain all the things I have tried but that will make this question unnecessarily long and perhaps result in losing some clarity. 我可以解释我尝试过的所有内容,但这会使问题变得不必要地冗长,并可能导致不清楚。 Greatly appreciate any help. 非常感谢您的帮助。

While responding to Q&A on SO I was trying some random stuff and at least this little piece of code below seems to work ( in terms of storing smaller/bigger values ) 在回应SO上的Q&A时,我尝试了一些随机的东西,至少下面这段代码似乎起作用了(就存储较小/较大的值而言)

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

stUSRREC userRecords[5];

Then manipulate it this way 然后这样操作

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

I have been able to write/rewrite different lengths (above) and can read all of them back correctly. 我已经能够写入/重写不同的长度(以上),并且可以正确读取所有长度。 Resizing "userRecords" might be a different game but that can wait a little 调整“ userRecords”的大小可能是一个不同的游戏,但可能会稍等

One thing I forgot to mention was that I will need to size/resize the array ( holding username ) ONLY ONCE. 我忘了提到的一件事是,我只需要一次调整大小/调整数组大小(持有用户名)。 In the setup() itself I can read/load the required data into those arrays. setup()本身中,我可以将所需的数据读取/加载到这些数组中。 I am not sure if that opens up any other possibility. 我不确定这是否有其他可能性。 The rest of the struct/array I need to manipulate during the running are only boolean and int values. 我在运行期间需要处理的其余结构/数组只是布尔值和整数值。 This is not an issue at all because there is no resizing required to do so. 这根本不是问题,因为不需要调整大小。

On a side note I am pretty sure I am not the only one who faced this situation. 从侧面讲,我很确定我不是唯一遇到这种情况的人。 Any tips/clues/pointers could be of help to many others. 任何提示/线索/指针可能会对许多其他人有所帮助。 The constraints on little devices like ESP32 become more visible when you really start loading them with a bunch of things. 当您真正开始向ESP32等小型设备加载一堆东西时,这些约束会变得更加明显。 I had it all working with "Strings" (the capital S) but the periodic reboot (cpu starvation?) required me to get rid of the Strings. 我已经使用“ Strings”(大写的S)完成了所有工作,但是定期重新启动(cpu饿死?)需要我摆脱Strings。 Even otherwise I hear that using Strings (on ESP, Arduino and gang) is a bad idea. 甚至我听说使用Strings(在ESP,Arduino和gang上)都是一个坏主意。

You tagged this question as C++, so I'll ask: 您将此问题标记为C ++,所以我会问:

Can you use vector and string in your embedded code? 您可以在嵌入式代码中使用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;

The use of string as the username type means you only allocate as many characters needed to hold the name instead of allocated an assumed max size of sizeOfUsername . 使用string作为用户名类型意味着您仅分配了保持名称所需的尽可能多的字符,而不是假定的sizeOfUsername最大大小。 The use of vector allows you to dynamically grow your record set. vector的使用使您可以动态增长记录集。

Then to add a new record: 然后添加新记录:

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

And you may not need NumOfrecs anymore. 而且您可能不再需要NumOfrecs That's covered by userRecrods.size() 这由userRecrods.size()覆盖

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM