我使用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,
,无法修复它。
平台:
我更新了完整的源代码。
#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;
}
答案 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.