【发布时间】:2017-11-29 03:16:22
【问题描述】:
在运行我的代码时(相关部分粘贴在下面),我会定期收到以下错误:
program(34010,0x70000e58b000) malloc: *** 对象错误 0x7fc43d93fcf0:被释放的指针未分配设置断点 在 malloc_error_break 中调试 Signal: SIGABRT (signal SIGABRT)
我在 Macbook (OS-10.13) 上运行多线程 C++ 代码,其中不同的线程同时使用相关代码。据我所知,只要我不在两个不同的线程中使用相同的“curl 句柄”(我理解为“CURL”又名“CURL *curl = curl_easy_init();”的一个实例),libcurl 确实是线程安全的同时。就我而言,由于每个线程分别调用该函数并初始化 CURL 对象的新实例,所以我应该是“安全的”,对吧?希望我遗漏了一些明显的东西,导致我(或在这种情况下为 lib curl)尝试释放已被释放的内存。如果我应该包含更多信息(如下),请随时告诉我。
seg错误的函数是
字符串 http_lib::make_get_request(字符串 url)
在写着
的那一行curl_easy_cleanup(curl);
有时(不经常)在一行上写着
res = curl_easy_perform(curl);
以下是我认为我的代码的相关部分:
size_t http_lib::CurlWrite_CallbackFunc_StdString(void *contents, size_t size, size_t nmemb, std::string *s)
{
size_t newLength = size*nmemb;
size_t oldLength = s->size();
try
{
s->resize(oldLength + newLength);
}
catch(std::bad_alloc &e)
{
//handle memory problem
return 0;
}
std::copy((char*)contents,(char*)contents+newLength,s->begin()+oldLength);
return size*nmemb;
}
string http_lib::make_post_request(string url, vector<string> headers, string post_params) {
CURL *curl;
CURLcode res;
curl = curl_easy_init();
string s;
if(curl)
{
struct curl_slist *chunk = NULL;
for(int i=0; i<headers.size(); i++){
/* Add a custom header */
chunk = curl_slist_append(chunk, headers[i].c_str());
}
/* set our custom set of headers */
res = curl_easy_setopt(curl, CURLOPT_HTTPHEADER, chunk);
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, post_params.c_str());
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //only for https
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); //only for https
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
if(networking_debug){
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //verbose output
}
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
{
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
}
/* always cleanup */
curl_easy_cleanup(curl);
}
// Debug output
if (networking_debug){
cout<<"Response: " << s <<endl;
}
return s;
}
string http_lib::make_get_request(string url) {
//SslCurlWrapper sslObject;
CURL *curl;
CURLcode res;
curl = curl_easy_init();
string s;
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, url.c_str());
//tell libcurl to follow redirection
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); //only for https
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); //only for https
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, CurlWrite_CallbackFunc_StdString);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &s);
if(networking_debug){
curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L); //verbose output
}
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
if (networking_debug){
cout << "Response: " << s << endl;
}
return s;
}
在 main() 我有
int main(int argc, char *argv[]){
// Initialize http_lib (curl)
curl_global_init(CURL_GLOBAL_DEFAULT);
... spin up 10 or so threads that make get/post requests to https site (some requests utilize the make_post_request() function and others utilize make_get_requet() function).
}
【问题讨论】:
-
不是在回调中显式调整和复制字符串,为什么不append接收到的字符串?
-
http_lib是什么?它是命名空间吗?是一堂课吗?如果是类,CurlWrite_CallbackFunc_StdString是静态成员函数吗? -
http_lib 只是我给函数所在的 hpp/cpp 文件起的名字。它不是一个类。只是我程序中与网络调用相关的功能的容器/命名空间。至于我为什么不追加,我没有充分的理由。
-
这只是一种感觉,但如果你尝试用
s->append((char *) contents, nmemb);替换该代码,它会变得更好吗? -
你的回调函数有错误的参数类型。
标签: c++ curl segmentation-fault libcurl