libcurl 中的内存泄漏
Memory leaks in libcurl
在对我的程序进行最后润色后,我 运行 valgrind 来检查内存泄漏。令我惊讶的是,我读到 huge 内存块被使用并且从未被释放,尽管我确保在结束程序之前释放了我正在使用的所有资源。仔细查看报告,我发现几乎所有报告都说泄漏来自 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)
这是 valgrind 抱怨的 url_fopen
函数:
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 忽略它们。如果不是,是否有解决此泄漏问题的方法?
尝试在程序开始时使用 curl_global_init(CURL_GLOBAL_DEFAULT);
。这设置了 libcURL
需要的环境。
建议,该函数在一个程序中至少调用一次。而且它不是线程安全的,所以它必须在程序的最开始调用,在任何线程启动之前。
此外,当您使用 libcURL
时,您应该在程序结束时为每次调用 curl_global_init()
调用一次 curl_global_cleanup();
。
这将清理 libcURL
.
使用的所有东西
在对我的程序进行最后润色后,我 运行 valgrind 来检查内存泄漏。令我惊讶的是,我读到 huge 内存块被使用并且从未被释放,尽管我确保在结束程序之前释放了我正在使用的所有资源。仔细查看报告,我发现几乎所有报告都说泄漏来自 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)
这是 valgrind 抱怨的 url_fopen
函数:
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 忽略它们。如果不是,是否有解决此泄漏问题的方法?
尝试在程序开始时使用 curl_global_init(CURL_GLOBAL_DEFAULT);
。这设置了 libcURL
需要的环境。
建议,该函数在一个程序中至少调用一次。而且它不是线程安全的,所以它必须在程序的最开始调用,在任何线程启动之前。
此外,当您使用 libcURL
时,您应该在程序结束时为每次调用 curl_global_init()
调用一次 curl_global_cleanup();
。
这将清理 libcURL
.