我有以下一些代码,我已经缩小到导致内存泄漏(也就是说,在任务管理器中,内存的私有工作集随着重复的输入字符串而增加)。我理解堆内存和堆栈的概念,以及避免内存泄漏的一般规则,但某些地方仍然存在问题:
while(!quit){
char* thebuffer = new char[210];
//checked the function, it isn't creating the leak
int size = FuncToObtainInputTextFromApp(thebuffer); //stored in thebuffer
string bufferstring = thebuffer;
int startlog = bufferstring.find("$");
int endlog = bufferstring.find("&");
string str_text="";
str_text = bufferstring.substr(startlog,endlog-startlog+1);
String^ str_text_m = gcnew String(str_text_m.c_str());
//some work done
delete str_text_m;
delete [] thebuffer;
}
我唯一能想到的是它可能是'string str_text'的创建,因为它永远不会超出范围,因为它只是在while中重新循环?如果是这样,我该如何解决?在while循环之外定义它不会解决它,因为它也会保持在范围内。任何帮助将不胜感激。
答案 0 :(得分:4)
您应该使用范围限制资源管理(也称为RAII),这在任何情况下都是很好的做法。永远不要手动分配内存,将其保存在自动分配的类中,该类将在析构函数中为您清理资源。
您的代码可能是:
while(!quit)
{
// completely safe, no leaks possible
std::vector<char> thebuffer(210);
int size = FuncToObtainInputTextFromApp(&thebuffer[0]);
// you never used size, this should be better
string bufferstring(thebuffer, size);
// find does not return an int, but a size_t
std::size_t startlog = bufferstring.find("$");
std::size_t endlog = bufferstring.find("&");
// why was this split across two lines?
// there's also no checks to ensure the above find
// calls worked, be careful
string str_text = bufferstring.substr(startlog, endlog - startlog + 1);
// why copy the string into a String? why not construct
// this directly?
String^ str_text_m = gcnew String(str_text_m.c_str());
// ...
// don't really need to do that, I think,
// it's garbage collected for a reason
// delete str_text_m;
}
重点是,如果确保您的资源可以自行释放,则不会出现内存泄漏。也许垃圾收集器会导致您的检漏仪误发射。
在旁注中,您的代码似乎有许多不必要的复制,您可能想要重新考虑复制字符串的次数。 (例如,在向量中找到"$"
和"&"
,然后从那里复制到str_text
,不需要中间副本。)
答案 1 :(得分:2)
你是#using std,所以str_text的类型是std :: string吗?也许你打算写 -
String^ str_text_m = gcnew String(str_text.c_str());
(而不是gcnew String(str_text_m.c_str()))?
最重要的是,使用gcnew分配一个String(或任何对象)声明你将不明确地删除它 - 你将它留给垃圾收集器。不确定如果删除它会发生什么(技术上它甚至不是指针。绝对不会引用CRT堆上的任何内容,其中new / delete有权力)。
您可以安全地评论str_text_m的删除。你可以期望逐渐增加内存(gcnew积累的地方)和突然减少(垃圾收集开始的地方)。
更好的是,你可以重复使用str_text_m,沿着 -
String^ str_text_m = gcnew String();
while(!quit){
...
str_text_m = String(str_text.c_str());
...
}
答案 2 :(得分:1)
我知道建议在删除它之后将释放的变量设置为NULL,以防止任何无效的内存引用。可能会有帮助,可能不会。
delete [] thebuffer;
thebuffer = NULL; // Clear a to prevent using invalid memory reference
答案 3 :(得分:0)
有一个名为DevPartner的工具可以在运行时捕获所有内存泄漏。如果您的应用程序有pdb,则会在应用程序中为您提供已观察到所有内存泄漏的行号。
这最适合用于非常大的应用程序。