识别C ++中的内存泄漏

时间:2010-06-16 20:24:13

标签: memory-leaks c++-cli

我有以下一些代码,我已经缩小到导致内存泄漏(也就是说,在任务管理器中,内存的私有工作集随着重复的输入字符串而增加)。我理解堆内存和堆栈的概念,以及避免内存泄漏的一般规则,但某些地方仍然存在问题:

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循环之外定义它不会解决它,因为它也会保持在范围内。任何帮助将不胜感激。

4 个答案:

答案 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,则会在应用程序中为您提供已观察到所有内存泄漏的行号。

这最适合用于非常大的应用程序。

相关问题