есть ли утечка памяти, правильно ли я освобождаю память - PullRequest
0 голосов
/ 10 января 2011

Уважаемые участники, я не понимаю, освобождаю ли я память в нужном месте или нет.специально * 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;  
}

Ответы [ 2 ]

7 голосов
/ 10 января 2011

Вы искали инструменты для обнаружения утечек памяти, такие как 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;
}

Эта программа очень просто выделяет 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

Почему?Потому что у вас нет delete d памяти, выделенной вам 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

Что произойдет, если вы освободитесь внутри вызова функции?Ну, на самом деле это нормально, кроме того, что в области действия этого кода есть переменная, которую вы можете случайно использовать.Если вы это сделаете, вы получите доступ к памяти, которую вы явно освободили, что, вероятно, приведет к сбою вашей программы.

Я предполагаю, что на каком-то этапе вы захотите использовать этот буфер в части A или B.в этом случае вам нужно, чтобы эта память еще была выделена.

Что касается только освобождения внутри оператора if, это гарантированная утечка памяти, если функция чтения не работает, потому что эта память никогда не освобождается.

Вот как вы должны это сделать:

//
// 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

Редактировать 4: Просто для пояснения:

Не смешивать malloc / free и new / delete . Если вы используете malloc, освободите эту память, если вы новичок, удалите эту память. Если вы взаимодействуете с кодом C, если для него не требуется массив типа int, вы можете использовать тип string, и нет необходимости в динамическом размещении. Если вы не переходите к функции C, которой не управляете, вам, вероятно, следует рассмотреть vector над массивом. Только если вы переходите к функции C, которую вы не можете контролировать, вам нужно войти в мир malloc и свободных методов C.

1 голос
/ 10 января 2011

Быстрое использование Ctrl + F (потому что вы опубликовали слишком много нерелевантного кода), показывает, что единственная память, которую вы выделяете, предназначена для * sResult, и до времени, когда вы освобождаете эту память, нет условий выхода, так что да,После просмотра этого кода я не решаюсь использовать фразу «вы делаете это правильно», но вы делаете это.

...