2015-01-24 1 views
3

После добавления последних штрихов к моей программе я запустил valgrind, чтобы проверить утечку памяти. И, к моему удивлению, я прочитал, что огромные куски памяти были использованы и никогда не были освобождены, хотя я убедился, что освободил каждый ресурс, который я использовал до окончания программы. Внимательно изучив отчет, я обнаружил, что почти во всех отчетах говорится, что утечки исходили из вызовов функций libcurl. Вот пример из доклада:Утечка памяти в libcurl

==3555== HEAP SUMMARY: 
==3555==  in use at exit: 179,937 bytes in 4,212 blocks 
==3555== total heap usage: 18,080 allocs, 13,868 frees, 10,050,116 bytes allocated 
==3555== 
==3555== Searching for pointers to 4,212 not-freed blocks 
==3555== Checked 486,368 bytes 
==3555== 
==3555== 2 bytes in 2 blocks are still reachable in loss record 1 of 667 
==3555== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3555== by 0x542C9C9: strdup (in /usr/lib/libc-2.20.so) 
==3555== by 0x4E58C1E: ??? (in /usr/lib/libcurl.so.4.3.0) 
==3555== by 0x4E6A90F: ??? (in /usr/lib/libcurl.so.4.3.0) 
==3555== by 0x4E6B4A0: curl_multi_perform (in /usr/lib/libcurl.so.4.3.0) 
==3555== by 0x404141: url_fopen (network.c:226) 
==3555== by 0x403737: load_tracks (PlayMusic.c:718) 
==3555== by 0x401E1C: main (PlayMusic.c:145) 
==3555== 
==3555== 2 bytes in 2 blocks are still reachable in loss record 2 of 667 
==3555== at 0x4C29F90: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==3555== by 0x542C9C9: strdup (in /usr/lib/libc-2.20.so) 
==3555== by 0x4E58C3A: ??? (in /usr/lib/libcurl.so.4.3.0) 
==3555== by 0x4E6A90F: ??? (in /usr/lib/libcurl.so.4.3.0) 
==3555== by 0x4E6B4A0: curl_multi_perform (in /usr/lib/libcurl.so.4.3.0) 
==3555== by 0x404141: url_fopen (network.c:226) 
==3555== by 0x403737: load_tracks (PlayMusic.c:718) 
==3555== by 0x401E1C: main (PlayMusic.c:145) 

Вот url_fopen функция, которая Valgrind жалуется:

URL_FILE *url_fopen(const char *url, const char *operation) 
{ 
    /* 
     this code could check for URLs or types in the 'url' and 
     basicly use the real fopen() for standard files 
    */ 

    URL_FILE *file; 

    file = malloc(sizeof(URL_FILE)); 
    if (!file) 
     return NULL; 

    memset(file, 0, sizeof(URL_FILE)); 

    if ((file->handle.file = fopen(url, operation))) 
     file->type = CFTYPE_FILE; /* marked as URL */ 

    else { 
     file->type = CFTYPE_URL; /* marked as URL */ 
     file->handle.curl = curl_easy_init(); 

     curl_easy_setopt(file->handle.curl, CURLOPT_URL, url); 
     curl_easy_setopt(file->handle.curl, CURLOPT_WRITEDATA, 
       file); 
     curl_easy_setopt(file->handle.curl, CURLOPT_VERBOSE, 
       0L); 
     curl_easy_setopt(file->handle.curl, 
       CURLOPT_WRITEFUNCTION, 
       write_callback); 

     if (!multi_handle) 
      multi_handle = curl_multi_init(); 

     curl_multi_add_handle(multi_handle, 
         file->handle.curl); 

     /* 
      lets start the fetch 
     */ 
     curl_multi_perform(multi_handle, 
        &file->still_running); 

     if ((file->buffer_pos == 0) && (!file->still_running)) { 
      /* 
       if still_running is 0 now, we should return NULL 
      */ 

      /* 
       make sure the easy handle is not in the multi handle anymore 
      */ 
      curl_multi_remove_handle(multi_handle, 
         file->handle.curl); 

      /* 
       cleanup 
      */ 
      curl_easy_cleanup(file->handle.curl); 
      curl_multi_cleanup(multi_handle); 
      fclose 
      free(file); 

      file = NULL; 
     } 
    } 
    return file; 
} 

Являются ли эти просто ложных срабатываний? Если да, то как я могу заставить valgrind игнорировать их. Если это не так, есть ли решение этой проблемы?

+0

Прочитайте документы, касающиеся 'curl_multi_perform', вам нужно проверить возвращаемое значение для' CURLM_CALL_MULTI_PERFORM', которое требует, чтобы он снова набрал ** ** немедленно **. Это может привести к утечке, хотя я не знаю, что это ваша проблема. – drahnr

+0

Связанные: http://stackoverflow.com/q/7866763/694576 – alk

ответ

5

Попробуйте использовать curl_global_init(CURL_GLOBAL_DEFAULT); в начале программы. Это устанавливает среду, требуемую libcURL.

Рекомендуется, чтобы эта функция вызывалась хотя бы один раз внутри программы. Также он не является потокобезопасным, поэтому его нужно вызывать в самом начале программы, прежде чем начнутся какие-либо потоки.

Также вы должны позвонить по телефону curl_global_cleanup(); один раз для каждого звонка до curl_global_init(), по окончании программы, когда вы закончите с использованием libcURL. Это очистит все, что используется libcURL.

 Смежные вопросы

  • Нет связанных вопросов^_^