libcurl无法获取CURLINFO_EFFECTIVE_URL

时间:2017-07-14 00:48:56

标签: c++ c linux libcurl

我使用curl_easy_getinfo获取网址,但有时指向私有内存,我该如何解决?

102 bool bb_curl::check_result(CURLcode code, CURL *handle, bool check_url) {
103     if (code == CURLE_OK) {
104         char *url = nullptr;
105         auto rc = curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &url);
106         if (rc == CURLE_OK && url && check_url) {
107             int http_code;
108             curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_code);
109             if (http_code == 200)
110                 BB_VERBOSE("[OK] %s\n", url);
111             else
112                 BB_Warn("[ERROR] http code:%d, url: %s\n", http_code, url);
113         }

使用gdb:

Program received signal SIGSEGV, Segmentation fault.
(gdb) f 5
#5  0x00002aaaac7b79a3 in bb_curl::check_result (this=0x6572f0, code=CURLE_OK, handle=0x6f4ab0,
check_url=true) at /wsp/bb_curl.cpp:110
110                     BB_VERBOSE("[OK] %s\n", url);
(gdb) p url
$1 = 0x2aaa00000000 <error: Cannot access memory at address 0x2aaa00000000>

我也设置CURLOPT_FOLLOWLOCATION, 1,,无法修复它。

更新

平台:

  1. gcc(GCC)4.9.3
  2. curl 7.46.0(x86_64-pc-linux-gnu)libcurl / 7.46.0 OpenSSL / 1.0.2e zlib / 1.2.3 libidn / 1.10 libssh2 / 0.19.0-20080814
  3. SUSE Linux Enterprise Server 11(x86_64)
  4. 我更新了完整的源代码。

    #include <curl/curl.h>
    
    #include <cstdlib>
    #include <string>
    #include <vector>
    #include <future>
    
    /* reserved vector */
    template <class T>
    inline std::vector<T> bb_reserved_vector(size_t n) {
        std::vector<T> vec;
        vec.reserve(n);
        return vec;
    }
    
    size_t write_cb(char *ptr, size_t size, size_t nmemb, void *userdata) {
        return size * nmemb;
    }
    
    bool check_result(CURLcode code, CURL *handle, bool check_url) {
        if (code == CURLE_OK && handle != nullptr) {
            char *url = nullptr;
            auto rc = curl_easy_getinfo(handle, CURLINFO_EFFECTIVE_URL, &url);
            if (rc == CURLE_OK && url && check_url) {
                int http_code;
                curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_code);
                if (http_code == 200)
                    printf("[OK] %s\n", url);
                else
                    printf("[ERROR] http code:%d, url: %s\n", http_code, url);
            }
            return true;
        } else {
            printf("[ERROR] curl code %d\n", code);
            return false;
        }
    }
    
    int main() {
        size_t sz = 1000;
        auto futures = bb_reserved_vector<std::future<CURLcode>>(sz);
        auto handles = bb_reserved_vector<CURL *>(sz);
        auto results = std::vector<std::string>(sz);
    
        curl_global_init(CURL_GLOBAL_ALL);
    
        for (size_t i = 0; i < sz; ++i) {
            handles.push_back(curl_easy_init());
            int curl_code = curl_easy_setopt(handles[i], CURLOPT_WRITEDATA, (void *) &results[i]);
            curl_code += curl_easy_setopt(handles[i], CURLOPT_URL, "www.example.com");
            curl_code += curl_easy_setopt(handles[i], CURLOPT_WRITEFUNCTION, write_cb);
            curl_code += curl_easy_setopt(handles[i], CURLOPT_FOLLOWLOCATION, 1);
            curl_code += curl_easy_setopt(handles[i], CURLOPT_NOSIGNAL, 1);
            if (curl_code != 0)
                printf("Set option error\n");
            auto fut = std::async(std::launch::async, curl_easy_perform, handles[i]);
            futures.push_back(std::move(fut));
        }
    
        // synchronize
        for (size_t i = 0; i < futures.size(); ++i) {
            futures[i].wait();
            check_result(futures[i].get(), handles[i], true);
        }
    
        // cleanup
        for (auto &item : handles)
            curl_easy_cleanup(item);
    
        curl_global_cleanup();
    
        return 0;
    }
    

2 个答案:

答案 0 :(得分:2)

似乎你犯了一个小而致命的错误。 http_code的类型应为long,而不是int。显然,对curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_code)的调用覆盖了url在CentOS上使用的内存。进行此更改修复了CentOS上的崩溃。请注意,64位Linux上的long为8字节,超过int

答案 1 :(得分:1)

可能是您发布的代码中没有错误。您有时可能会传递无效的CURL* handle

我检查了这个,实际上,如果你传递了一个无效的句柄,函数curl_easy_getinfo仍然会返回CURLE_OK。如果您尝试访问char* url变量,则稍后会发生分段错误。 propgram(用g++ main.cpp -lcurl编译)

#include <iostream>
#include <curl/curl.h>

using namespace std;

int main(void){
    char* url;
    CURL *handle;
    handle=curl_easy_init();
    curl_easy_setopt(handle, CURLOPT_URL, "http://www.example.com");
    CURL *bug=(CURL*)((long)(handle)+1);
    CURLcode code= curl_easy_getinfo(bug, CURLINFO_EFFECTIVE_URL, &url);    
    cout<<"CURLE_OK="<<CURLE_OK<< " and code="<<code<<endl;
    cout <<"URL: "<<url; //This line causes segmentation fault;
    curl_easy_cleanup(handle);
    return EXIT_SUCCESS;
}

产生类似的东西:

CURLE_OK=0 and code=0
Program received signal SIGSEGV, Segmentation fault.