2014-05-14 52 views
0

我寫了一個簡單的curl get wrapper來訪問http,https內容。如果我用valgrind運行我的測試用例,我可以看到一些仍然可到達的扇區。是的,我知道他們沒有失去引用或絕對丟失。但我想保持我的項目清潔。如何在沒有memleak災難的情況下使用curl + ssl

如果我通過curl_global_init(CURL_GLOBAL_NOTHING)禁用SSL,則不會檢測到任何內存。但是,那麼也沒有https支持。所以我猜它是一個libcrypt,libssl的問題?我能做些什麼來正確初始化並清除https curl調用,而無需使用valgrind通知?

[email protected]:rcc$ valgrind --leak-check=full --show-reachable=yes ./tests/testsuite 
==7171== Memcheck, a memory error detector 
==7171== Copyright (C) 2002-2011, and GNU GPL'd, by Julian Seward et al. 
==7171== Using Valgrind-3.7.0 and LibVEX; rerun with -h for copyright info 
==7171== Command: ./tests/testsuite 
==7171== 
==7171== Conditional jump or move depends on uninitialised value(s) 
==7171== at 0x703784B: ASN1_STRING_set (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x702552C: ASN1_mbstring_ncopy (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x7025753: ASN1_mbstring_copy (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x7026614: ASN1_STRING_to_UTF8 (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x7027A42: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x7027FA6: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x702E4E2: ASN1_item_ex_d2i (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x702F09F: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x702F2E7: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x702EB50: ASN1_item_ex_d2i (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x702F09F: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x702F2E7: ??? (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== 
OK (3) 
==7171== 
==7171== HEAP SUMMARY: 
==7171==  in use at exit: 64 bytes in 2 blocks 
==7171== total heap usage: 10,535 allocs, 10,533 frees, 898,726 bytes allocated 
==7171== 
==7171== 32 bytes in 1 blocks are still reachable in loss record 1 of 2 
==7171== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==7171== by 0x6F821FF: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x700A82E: sk_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x6D012A9: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0) 
==7171== by 0x6D031F8: SSL_COMP_get_compression_methods (in /lib/x86_64-linux-gnu/libssl.so.1.0.0) 
==7171== by 0x6D08618: SSL_library_init (in /lib/x86_64-linux-gnu/libssl.so.1.0.0) 
==7171== by 0x549A1E2: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.2.0) 
==7171== by 0x54A1B89: curl_global_init (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.2.0) 
==7171== by 0x559240: RCC::IO::HttpClient::get(std::string) (HttpClient.cpp:53) 
==7171== by 0x559FFE: HttpClientTest::testBasicRequest() (HttpClientTest.cpp:55) 
==7171== by 0x55BB11: CppUnit::TestCaller<HttpClientTest>::runTest() (TestCaller.h:166) 
==7171== by 0x56FA081: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0) 
==7171== 
==7171== 32 bytes in 1 blocks are still reachable in loss record 2 of 2 
==7171== at 0x4C2B3F8: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) 
==7171== by 0x6F821FF: CRYPTO_malloc (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x700A84C: sk_new (in /lib/x86_64-linux-gnu/libcrypto.so.1.0.0) 
==7171== by 0x6D012A9: ??? (in /lib/x86_64-linux-gnu/libssl.so.1.0.0) 
==7171== by 0x6D031F8: SSL_COMP_get_compression_methods (in /lib/x86_64-linux-gnu/libssl.so.1.0.0) 
==7171== by 0x6D08618: SSL_library_init (in /lib/x86_64-linux-gnu/libssl.so.1.0.0) 
==7171== by 0x549A1E2: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.2.0) 
==7171== by 0x54A1B89: curl_global_init (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.2.0) 
==7171== by 0x559240: RCC::IO::HttpClient::get(std::string) (HttpClient.cpp:53) 
==7171== by 0x559FFE: HttpClientTest::testBasicRequest() (HttpClientTest.cpp:55) 
==7171== by 0x55BB11: CppUnit::TestCaller<HttpClientTest>::runTest() (TestCaller.h:166) 
==7171== by 0x56FA081: CppUnit::TestCaseMethodFunctor::operator()() const (in /usr/lib/libcppunit-1.12.so.1.0.0) 
==7171== 
==7171== LEAK SUMMARY: 
==7171== definitely lost: 0 bytes in 0 blocks 
==7171== indirectly lost: 0 bytes in 0 blocks 
==7171==  possibly lost: 0 bytes in 0 blocks 
==7171== still reachable: 64 bytes in 2 blocks 
==7171==   suppressed: 0 bytes in 0 blocks 
==7171== 
==7171== For counts of detected and suppressed errors, rerun with: -v 
==7171== Use --track-origins=yes to see where uninitialised values come from 
==7171== ERROR SUMMARY: 4 errors from 1 contexts (suppressed: 2 from 2) 

的捲曲包裝(它的重要組成部分):

static size_t WriteCallback(void *contents, size_t size, size_t nmemb, void *userp) 
{ 
    ((std::string*)userp)->append((char*)contents, size * nmemb); 
    return size * nmemb; 
} 

std::string HttpClient::get(std::string url) 
{ 
    curl_global_init(CURL_GLOBAL_ALL); 

    CURL *curl = NULL; 
    CURLcode result; 
    std::string readBuffer = ""; 

    curl = curl_easy_init(); 

    if (curl == 0) 
     throw std::runtime_error("Unable to create CURL instance"); 

    if (useProxy) 
     curl_easy_setopt(curl, CURLOPT_PROXY, proxyHost.c_str()); 

    if (useAuth) 
     authenticate(curl);  

    if (followRedirect) 
     curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1); 


    LOG_DEBUG("http client fetch " + url);  

    curl_easy_setopt(curl, CURLOPT_URL, url.c_str());  
    curl_easy_setopt(curl, CURLOPT_POST, false); 
    curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, WriteCallback); 
    curl_easy_setopt(curl, CURLOPT_WRITEDATA, &readBuffer); 

    result = curl_easy_perform(curl); 

    if (result != CURLE_OK) { 
     curl_easy_cleanup(curl); 
     throw std::runtime_error(curl_easy_strerror(result)); 
    } 

    curl_easy_cleanup(curl);   
    curl_global_cleanup(); 

    return readBuffer; 
} 

運行測試有:

valgrind --leak-check=full --show-reachable=yes -v ./tests/testsuite 
+0

是的我64字節是足以抱怨。你的限制在哪裏?我不知道它是否會在多次通話中倍增。我不知道我的清理是否正確。所以我問一個問題。這真的很糟糕嗎? – jami

+4

問題可能僅僅是OpenSSL在加載時動態分配一些數據,並且在進程的整個生命週期中都使用這些數據。某種每進程(或每線程)數據。由於它應該用於進程的整個生命週期,所以不需要釋放它,因爲當進程結束時它將由操作系統完成。 –

回答

0

好吧,我接受約阿希姆Pileborg(下注釋的很好的答案主要問題)。 OpenSSL使用每個進程中的一些數據,這些數據在我的程序的生命週期中仍然存在。所以valgrind發現它仍然可以訪問,我的OpenSSL初始化/定稿似乎是正確的。謝謝約阿希姆

相關問題