libcurl 无法获取 CURLINFO_EFFECTIVE_URL

Ste*_*eve 3 c c++ linux libcurl

我用来curl_easy_getinfo获取url,但有时它指向私有内存,我该如何解决?

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

使用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>
Run Code Online (Sandbox Code Playgroud)

我也设置了CURLOPT_FOLLOWLOCATION, 1,,修复不了

更新

平台:

  1. 海湾合作委员会(海湾合作委员会)4.9.3
  2. 卷曲 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 企业服务器 11 (x86_64)

我更新了完整的源代码。

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

Yon*_* Wu 5

看来你犯了一个小但致命的错误。的类型http_code应该long代替int。显然,调用curl_easy_getinfo(handle, CURLINFO_RESPONSE_CODE, &http_code)覆盖了 CentOS 上使用的内存url。进行此更改修复了我在 CentOS 上的崩溃问题。请注意,long在 64 位 Linux 上为 8 个字节,比int.