是否有内存泄漏,我正确释放内存

sam*_*rat -3 c++ memory-leaks

亲爱的各位议员,我对是否在正确的地方释放记忆感到困惑.特别是*sResult?

int ReadToSerialPort( char *psResponse, int iMax)  
{  

    size_t iIn;  

    if ( fd < 1 )  
    {  
        printf( "port is not open\n" );  
        return -1;  
    }       

    iIn = read( fd, psResponse, iMax-1 );     
    if ( iIn < 0 )      
    {
        if ( errno == EAGAIN )  
        {  
            printf( "The errror in READ" );  
            return 0; // assume that command generated no response      
        }  
        else  
            printf( "read error %d %s\n", errno, strerror(errno) );  

   }  
   else   
 psResponse[(int)iIn<(int)iMax?iIn:iMax] = '\n';   

  return iIn;   

} // end ReadAdrPort  
int MultiQuery ()  
{  
    // check database connectivity   

 // code to check  DB

     while (1)  
     { //while start   

         // char *sResult = NULL;  
          char  *sResult = (char *)malloc(4096);   

          // Reading from H/W  
          if ( ( ReadToSerialPort(sResult,4096) ) > 0 )      
          {   

              // code to trim read line and put into db....   



            printf(" before free is %s\n", sResult);   

             free(sResult);        
             sResult = NULL;    
         } // end ifReadToSerialPort >0     

        //*sResult = NULL;    


     } // while(1) ends;      

    fclose(errorlog);  
    fclose(errorlog2);   
    mysql_close(&mysql);   
    return 0;  
}
Run Code Online (Sandbox Code Playgroud)

小智 7

你有没有研究过检测内存泄漏的工具,比如Valgrind?(Windows替代品)

在代码上运行这些代码将向您显示您泄漏的内存量,并且可能在哪里.

这不是一个完整的程序,所以我们无法为您传递它.一些忠告:

  • 分解例程并具有单独的测试可执行文件,以便您可以确保代码中的一些内容没有内存泄漏.这有点像测试驱动开发 - 您为函数编写测试以确保它正常工作并正确验证输入,并且您也测试它是否存在内存泄漏.
  • 像时尚一样在图书馆中发展.这应该是第二天性,因为它优化了代码重用(不要重复自己,除非重复自己是有利的)并且有助于上述.

编辑:我将扩展它.为了让您了解内存泄漏何时发生,请考虑以下事项:

#include <iostream>

using namespace std;

int main(int argc, char** argv)
{
    int* arr = new int(5);
    // delete arr; // <-- uncomment this to fix memalloc bug.
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

这个程序非常简单地在堆上分配4个字节,然后退出而不整理那个内存.

Valgrind会告诉你:

HEAP SUMMARY:
==23008==     in use at exit: 4 bytes in 1 blocks
==23008==   total heap usage: 1 allocs, 0 frees, 4 bytes allocated
==23008== 
==23008== LEAK SUMMARY:
==23008==    definitely lost: 4 bytes in 1 blocks
==23008==    indirectly lost: 0 bytes in 0 blocks
==23008==      possibly lost: 0 bytes in 0 blocks
==23008==    still reachable: 0 bytes in 0 blocks
==23008==         suppressed: 0 bytes in 0 blocks
Run Code Online (Sandbox Code Playgroud)

为什么?因为你没有delete分配的内存new.粗略地说,这很复杂.

我说复杂,因为程序变得很快,内存泄漏突然变得更加复杂.谁分配了内存?谁释放了它?内存是作为库的一部分分配的吗?开始使用数组时会发生什么?通过释放阵列的外部级别而不是内部级别,可能会导致间接内存丢失.请参阅间接记忆丧失.

这很快变得非常复杂,特别是当函数开始分配内存并开始在别处使用它们时,您开始依赖于编程确定的内存大小,例如基于用户输入的字符串长度.该maxlen+1错误是常见的错误,可以在数据的较大二维数组做出巨大的泄漏.

根据您的新问题修改2:

首先,如果你正在使用C++,我强烈建议忘记malloc.使用new并delete因为它们理解多态性和对象,而malloc不是.您的构造函数可能无法正确调用.如果您需要字符串,请使用该string类型.如果你需要数组,vector通常会这样做.

其次,如果读取操作正常,则只释放内存.为什么?您仍然分配了内存,因此无论读取操作是否有效,您仍然需要释放内存.您还应该检查内存是否确实已分配,否则您将因访问您不应访问的内存而导致分段错误.

编辑三:

好的,根据您的意见,请考虑以下代码,我认为您提出的是:

char* buffer = (char*)malloc(4096*sizeof(char));

if ( ReadToSerialPort(buffer, ...) > 0 ) // you are proposing to free in this func call
{
    // do stuff A

}

// do stuff B

// free(buffer); // <-- you should free buffer here
Run Code Online (Sandbox Code Playgroud)

如果你在函数调用中释放会发生什么?嗯,这实际上还不错,除了你可能会意外使用的代码范围内仍有一个变量.如果这样做,您将访问已明确发布的内存,这可能会导致程序崩溃.

我假设在某个阶段你想在A部分或B部分使用这个缓冲区.在这种情况下你需要分配内存.

至于只在if语句中释放,如果read函数不起作用,这是一个保证的内存泄漏,因为该内存永远不会被释放.

这是你应该怎么做的:

//
// I maintain you should use a string here, or 
// if you insist on char*, use new.
// and delete.
//
char* buffer = (char*)malloc(4096*sizeof(char)); 

if ( buffer == NULL )
{
    // os refused the alloc.
    cout << "Out of memory\n" << endl;
    return 1;
}

if ( ReadToSerialPort(buffer, ...) > 0 ) // this call frees as well?
{
    // do stuff A using buffer

}

// do stuff B using buffer

free(buffer); // <-- you should free buffer here
Run Code Online (Sandbox Code Playgroud)

编辑4:只是为了澄清:

不要混合malloc/free和new/delete.如果你是malloc,释放那个内存,如果是新的,删除那个内存.如果你正在与C代码接口,除非它需要类似int的数组,你可以使用该string类型,不需要动态分配.除非你传递给C函数你无法控制,否则你应该考虑vector在数组之上.只有当你传递给C函数时,如果你需要进入C的malloc和free方法的世界,你就无法控制.