简体   繁体   English

libcurl-“ curl_easy_cleanup()”导致malloc错误(C ++)

[英]libcurl - “curl_easy_cleanup()” is causing malloc error (C++)

When running my code (pertinent sections pasted below), I periodically get the following error: 运行我的代码时(下面粘贴了相关的部分),我会定期收到以下错误:

program(34010,0x70000e58b000) malloc: *** error for object 0x7fc43d93fcf0: pointer being freed was not allocated set a breakpoint in malloc_error_break to debug Signal: SIGABRT (signal SIGABRT) 程序(34010,0x70000e58b000)malloc:***对象0x7fc43d93fcf0的错误:未分配释放的指针在malloc_error_break中设置了一个断点来调试信号:SIGABRT(信号SIGABRT)

I am running multi-threaded C++ code on a Macbook (OS-10.13) wherein different threads make use of the code in question simultaneously. 我在Macbook(OS-10.13)上运行多线程C ++代码,其中不同的线程同时使用有问题的代码。 To my knowledge, libcurl is indeed thread safe as long as I do not utilize the same "curl handle" (which I understand to be an instance of "CURL" aka "CURL *curl = curl_easy_init();") in two different threads at the same time. 据我所知,libcurl确实是线程安全的,只要我在两个不同的线程中不使用相同的“ curl句柄”(我理解为“ CURL”的实例,又称为“ CURL * curl = curl_easy_init();”)即可。与此同时。 In my case, since each thread calls the function separately and initializes a new instance of a CURL object, I should be "safe", right? 就我而言,由于每个线程分别调用该函数并初始化CURL对象的新实例,所以我应该是“安全的”,对吗? Hopefully there is something obvious that I'm missing that is causing me (or lib curl in this case) to attempt to free memory that has already been freed. 希望我遗漏了一些明显的东西,导致我(在这种情况下为lib curl)尝试释放已经释放的内存。 If there is any more information I should have included (below) please don't hesitate to let me know. 如果还有其他我应该包括的信息(下),请随时告诉我。

The function that seg faults is 段故障的功能是

string http_lib::make_get_request(string url) 字符串http_lib :: make_get_request(字符串url)

on the line that reads 在读取的行上

curl_easy_cleanup(curl); curl_easy_cleanup(curl);

and sometimes (less often) on the line that reads 有时(不经常)在读取的行上

res = curl_easy_perform(curl); res = curl_easy_perform(curl);

Below is what I think would be the pertinent sections of my code: 以下是我认为是代码相关部分的内容:

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;
}

In main() I have 在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). 
}

CMAKE doesn't/didn't seem to want to use anything other than CURL_ROOT_DIR of "/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include" for libcurl (aka curl). 除了“ /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk/usr/include”的CURL_ROOT_DIR之外,CMAKE似乎/不想使用其他任何东西。用于libcurl(又名curl)。

Thus it was using the curl lib that mac (and/or Xcode) ships with. 因此,它使用的是mac(和/或Xcode)随附的curl lib。 I haven't figured out what version that is, but I can say that not using it and instead using CURL version 7.57 is what fixed my issue. 我还没有想通了,是什么版本,但我可以说, 使用它,而是使用curl版本7.57是什么固定我的问题。

I used "brew" package manager to 我使用“酿造”包装管理器

brew install curl

Doing so created /usr/local/Cellar/curl/7.57.0 directory and put all libs/includes in there. 这样就创建了/usr/local/Cellar/curl/7.57.0目录,并将所有libs / includes放在其中。

Then I added 然后我加了

 -I/usr/local/Cellar/curl/7.57.0/include -L/usr/local/Cellar/curl/7.57.0/lib

to my CMAKE CMAKE_CXX_FLAGS. 到我的CMAKE CMAKE_CXX_FLAGS。

TLDR; TLDR; Solution was to ensure I was using the newest version of the curl lib. 解决方案是确保我使用的是最新版本的curl lib。 Now that I am, no problem. 现在我没问题了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM