libcurl中的内存泄漏

Amr*_*man 4 c valgrind memory-leaks libcurl

在我的程序中添加最后的触摸后,我运行valgrind来检查内存泄漏.让我吃惊,我读了大量被使用的内存块,永远不会释放,但我确信我释放我结束程序之前,利用一切资源.仔细观察报告,我发现几乎所有报告都说泄漏来自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)
Run Code Online (Sandbox Code Playgroud)

这是url_fopenvalgrind抱怨的功能:

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;
}
Run Code Online (Sandbox Code Playgroud)

这些只是误报吗?如果是,我怎么能强迫valgrind忽略它们.如果不是,那么这个泄漏问题是否有解决方案?

小智 6

尝试curl_global_init(CURL_GLOBAL_DEFAULT);在程序开始时使用.这设置了libcURL所需的环境.

建议在程序中至少调用一次此函数.它也不是线程安全的,因此必须在程序的最开始,在任何线程启动之前调用它.

此外,在完成使用后,您应该在程序结束时拨打curl_global_cleanup();一次电话.这将清理所有使用的东西.curl_global_init()libcURLlibcURL