C++ C++;内存泄漏,我可以';找不到
我这里有一个关于粒子光子的小示例程序,它有一个我无法理解的内存缺陷 它的作用:加载一个带有小字符串块的缓冲区,将大缓冲区转换回字符串。然后它创建一组对象,这些对象只是缓冲区小块的包装器。它会重复执行此操作,在setup()之后我不会分配任何新内存,但内存会缓慢下降,直到崩溃 main.cpp 包括,变量声明 设置功能、分配内存、初始分配 编辑:C++ C++;内存泄漏,我可以';找不到,c++,memory-management,memory-leaks,microcontroller,C++,Memory Management,Memory Leaks,Microcontroller,我这里有一个关于粒子光子的小示例程序,它有一个我无法理解的内存缺陷 它的作用:加载一个带有小字符串块的缓冲区,将大缓冲区转换回字符串。然后它创建一组对象,这些对象只是缓冲区小块的包装器。它会重复执行此操作,在setup()之后我不会分配任何新内存,但内存会缓慢下降,直到崩溃 main.cpp 包括,变量声明 设置功能、分配内存、初始分配 编辑: 这是我面临的一个真正的问题,我不知道为什么它会被否决。帮帮我,我怎么能说得更清楚?我不愿意收缩代码,因为它模仿了一个更大的程序的许多方面,只是简单地建模
这是我面临的一个真正的问题,我不知道为什么它会被否决。帮帮我,我怎么能说得更清楚?我不愿意收缩代码,因为它模仿了一个更大的程序的许多方面,只是简单地建模。我想保留代码的结构,以防这个bug是一个紧急属性 所以,经过一些测试后,我想向给出正确答案的罗斯舒尔茨(Russ Schultz)大喊一声。如果您想正式发布解决方案,我很乐意将其标记为正确 内存错误是由于分配char buffer\u容器而没有考虑null终止字符引起的,这意味着我正在加载一个太大的字符串。(不完全确定这为什么会导致错误并且不会抛出错误?) 然而,在另一个网站上,我也收到了以下建议:
字符串块;
对于(字符i=0;i<200;i++){
int index=rand()%字母范围;
chunk.append(字母表.substr(索引,1));
//strcat(缓冲区、字母表、子字符串(索引、索引+1));
num_chars++;
}
我觉得这个循环很可疑。您需要依靠stringappend方法根据需要增长块,但您知道您将运行该循环200次。为什么不使用stringreserve方法来分配那么多空间呢?我敢打赌,当您调用realloc时,添加的每个新字符都会占用大量内存,这可能会导致内存碎片
这最终不是解决方案,但知道这一点可能会很好 始终考虑字符串终止符:
DummyClass(string input){
_container = new char[input.length()];
strcpy(_container, input.c_str());
}
分配太少的一个字节来保存输入字符串和终止符,然后将其复制到其中。最后附加的\0
正在覆盖某些内容,这很可能是成功地将分配的内存片段重新集成回堆所需的元数据。我真的很惊讶它没有崩溃
可能不会每次分配都发生这种情况(仅当您溢出到一个新的8字节对齐块中时才会发生),但一次就足够了:)对于这种格式来说,代码太多了。请出示一张支票。valgrind等工具可以帮助您缩小问题范围,使用调试信息编译代码以获得更精确的结果。这不会导致泄漏,而是在
~DummyClass()
replacedelete\u容器中代码>使用删除[]\u容器代码>不确定这是否会导致泄漏,但分配\u container=new char[input.length()]可能会导致不好的事情发生然后是strcpy(_容器,input.c_str())
(您没有为\0
分配空间)作为一种调试策略,为每个DummyClass()
添加一个全局对象id。每次创建新对象时,增加id并将其添加到地图或所选集合中。删除时,请将其从集合中删除。一段时间后,检查以确保集合为空。这样,您可以确保删除正在创建的每个对象。另一个小问题是析构函数会盲目删除\u容器
。如果您有一个使用默认构造函数创建的对象,\u container
未定义,因此您的行为将未定义。我不认为上述代码中会发生这种情况,但有一点需要担心。当您在空闲存储区中溢出缓冲区时,它可能会损坏有关已分配内存或其他已分配内存的信息。结果可能是崩溃、泄漏或数据损坏。取决于被覆盖的数据是什么。为什么人们一直对我投反对票。我很困惑。我认为这个网站的目的是提问和传播知识。我在这里所做的就是问一个关于我所遇到的问题的问题,尽量表现得友善,并对答案给予肯定。我的名声已经很低了;我觉得自己受到了极不公平的对待,我绝对不会被鼓励去寻求更多的帮助。我对这个问题投了更高的票,因为你显然付出了很多努力,尽管我不建议你在问题或答案中添加太多的元评论(大多数读者对此不感兴趣,而且经常被删掉)。对于您的答案,我倾向于建议,如果您正在添加一个附录,但其他人广泛解决了它,您可以将其设置为社区Wiki,这意味着对它的任何投票都不会影响您的分数。(我认为C++标签确实对MCVE更严格——这可能是那些倾向于低级语言的人的苛刻本性。如果你得到了几张下注,那么不用担心——评论说不幸的人可以吸引更多的人!)
bool delete_objects()
{
Serial.println("deleting objects in 'store'");
for(auto iter = store.begin(); iter != store.end(); iter++)
{
delete iter->second;
iter->second = nullptr;
}
store.clear();
if(store.empty())
return true;
else
return false;
}
void setup()
{
Serial.begin(9600);
Serial1.begin(38400);
delay(2000);
buffer = new char[9000];
alphabet = string("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789~!@#$^&*()_-?/><[]{}|");
alphabet_range = alphabet.length() - 1;
state = STATE_INIT;
num_chars = 0;
}
void loop()
{
switch(state){
case STATE_INIT: {
strcpy(buffer, "");
state = STATE_LOAD_BUFFER;
delay(1000);
break;
}
case STATE_LOAD_BUFFER: {
if(num_chars < 6000){
string chunk;
for(char i = 0; i < 200; i++){
int index = rand() % alphabet_range;
chunk.append(alphabet.substr(index, 1));
num_chars++;
}
strcat(buffer, chunk.c_str());
}
else{
num_chars = 0;
state = STATE_PREP_FOR_DESERIALIZE;
}
delay(500);
break;
}
case STATE_PREP_FOR_DESERIALIZE: {
Serial.println("\nAttempting to delete current object set...");
delay(500);
if(delete_objects())
Serial.println("_delete_objects succeeded");
else {
Serial.println("_delete_objects failed");
break;
}
state = STATE_FAKE_DESERIALIZE;
delay(1000);
break;
}
case STATE_FAKE_DESERIALIZE: {
string buff_string(buffer);
if(buff_string.length() == 0){
Serial.println("Main:: EMPTY STRING CONVERTED FROM BUFFER");
}
int index = 0;
int key = 1;
while(index < buff_string.length())
{
int amount = (rand() % 50) + 5;
DummyClass* dcp = new DummyClass(buff_string.substr(index, amount));
store[key] = dcp;
index += amount;
key++;
}
state = STATE_FINISH_RESTART;
delay(1000);
break;
}
case STATE_FINISH_RESTART: {
state = STATE_INIT;
break;
}
}
}
using namespace std;
class DummyClass {
private:
char* _container;
public:
DummyClass(){
}
DummyClass(string input){
_container = new char[input.length()];
strcpy(_container, input.c_str());
}
~DummyClass(){
delete _container;
_container = nullptr;
}
char* ShowMeWhatYouGot(){
return _container;
}
};
string chunk;
for(char i = 0; i < 200; i++){
int index = rand() % alphabet_range;
chunk.append(alphabet.substr(index, 1));
// strcat(buffer, alphabet.substring(index, index + 1));
num_chars++;
}
DummyClass(string input){
_container = new char[input.length()];
strcpy(_container, input.c_str());
}