为什么 libcurl 在清理调用后仍然留下可访问的块?
Why libcurl still leaves reachable blocks after cleanup calls?
我一直在使用 libcurl 来处理 get/post 请求,而 valgrind 总是向我显示相同数量的可访问块 (21)。我在标准 cURL 的配置中缺少什么来避免这种情况?
这是最简单的代码 "error":
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
int main(int argc, char const *argv[]) {
CURL *curl;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
·
·
·
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
我用
编译
$ gcc -o test cURL.c -lcurl
Valgrind 检查
$ valgrind --leak-check=full --track-origins=yes ./test
==4295== Memcheck, a memory error detector
==4295== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4295== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==4295== Command: ./test
==4295==
==4295==
==4295== HEAP SUMMARY:
==4295== in use at exit: 858 bytes in 21 blocks
==4295== total heap usage: 4,265 allocs, 4,244 frees, 185,353 bytes allocated
==4295==
==4295== LEAK SUMMARY:
==4295== definitely lost: 0 bytes in 0 blocks
==4295== indirectly lost: 0 bytes in 0 blocks
==4295== possibly lost: 0 bytes in 0 blocks
==4295== still reachable: 858 bytes in 21 blocks
==4295== suppressed: 0 bytes in 0 blocks
==4295== Reachable blocks (those to which a pointer was found) are not shown.
==4295== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==4295==
==4295== For counts of detected and suppressed errors, rerun with: -v
==4295== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
libcurl 链接到许多库,其中一些库没有像 curl_global_cleanup
这样的函数,可以恢复初始化并释放所有内存。当 libcurl 链接到 NSS 以获得 TLS 支持时,以及 libssh2 和它对 libgcrypt 的使用时,就会发生这种情况。 GNUTLS 作为 TLS 实现在这方面更简洁。
一般来说,这不是问题,因为这些辅助库仅用于在进程终止时释放内存的操作系统,因此不需要显式清理(甚至会减慢进程终止速度)。仅对于某些内存调试器,缺少清理例程的影响是可见的,而 valgrind 通过区分实际泄漏(没有指针指向的内存)和进程终止时仍可访问的内存(以便它可以有如果进程没有终止,则再次使用)。
我一直在使用 libcurl 来处理 get/post 请求,而 valgrind 总是向我显示相同数量的可访问块 (21)。我在标准 cURL 的配置中缺少什么来避免这种情况?
这是最简单的代码 "error":
#include <stdio.h>
#include <stdlib.h>
#include <curl/curl.h>
int main(int argc, char const *argv[]) {
CURL *curl;
curl_global_init(CURL_GLOBAL_ALL);
curl = curl_easy_init();
·
·
·
curl_easy_cleanup(curl);
curl_global_cleanup();
return 0;
}
我用
编译$ gcc -o test cURL.c -lcurl
Valgrind 检查
$ valgrind --leak-check=full --track-origins=yes ./test
==4295== Memcheck, a memory error detector
==4295== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==4295== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==4295== Command: ./test
==4295==
==4295==
==4295== HEAP SUMMARY:
==4295== in use at exit: 858 bytes in 21 blocks
==4295== total heap usage: 4,265 allocs, 4,244 frees, 185,353 bytes allocated
==4295==
==4295== LEAK SUMMARY:
==4295== definitely lost: 0 bytes in 0 blocks
==4295== indirectly lost: 0 bytes in 0 blocks
==4295== possibly lost: 0 bytes in 0 blocks
==4295== still reachable: 858 bytes in 21 blocks
==4295== suppressed: 0 bytes in 0 blocks
==4295== Reachable blocks (those to which a pointer was found) are not shown.
==4295== To see them, rerun with: --leak-check=full --show-leak-kinds=all
==4295==
==4295== For counts of detected and suppressed errors, rerun with: -v
==4295== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
libcurl 链接到许多库,其中一些库没有像 curl_global_cleanup
这样的函数,可以恢复初始化并释放所有内存。当 libcurl 链接到 NSS 以获得 TLS 支持时,以及 libssh2 和它对 libgcrypt 的使用时,就会发生这种情况。 GNUTLS 作为 TLS 实现在这方面更简洁。
一般来说,这不是问题,因为这些辅助库仅用于在进程终止时释放内存的操作系统,因此不需要显式清理(甚至会减慢进程终止速度)。仅对于某些内存调试器,缺少清理例程的影响是可见的,而 valgrind 通过区分实际泄漏(没有指针指向的内存)和进程终止时仍可访问的内存(以便它可以有如果进程没有终止,则再次使用)。