使用字符串 throws bad_alloc 为用户数据卷曲写入回调

Curl write callback with string throws bad_alloc for user data

我定义了这样一个 CurlHelper:

/*CurlHelper.hpp */
class CurlHelper
{
public:
    ...

    CURLcode RunCurl(void);

    CURLcode CurlRead(long timeout);

    size_t WriteCallback(void * contents, size_t size, size_t nb, string* userData);

    string getDataBuffer(void);    
    ....

private:
    CURL *m_curl;
    string m_url;
    string m_urlResponseData;
};



/* CurlHelper.cpp*/
size_t CurlHelper::WriteCallback(void * contents, 
                                  size_t size, 
                                  size_t nmemb, 
                                  string * userData)
{
    size_t realSize = size * nmemb;

    if(userData)
    {
        userData->append(static_cast<const char *>(contents), realSize);
    }

    return realSize;
}

CURLcode CurlHelper::CurlRead(long timeout)
{
    CURLcode ec = CURLE_UNKNOWN_OPTION;

    if(!m_url.empty())
        cout << " m_url: " << m_url.c_str() << endl;

    if(m_curl)
    {
        if(CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, &CurlHelper::WriteCallback))
                && CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, 1L))
                && CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1L))
                && CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, &m_urlResponseData))
                && CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_TIMEOUT, timeout))
                && CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str())))
        {
            cout << "Successfully set CURL Read options"<< endl;
        }
    }

    return ec;
}

CURLcode CurlHelper::RunCurl(void)
{
    if(m_urlResponseData.empty())
        cout << " m_urlResponseData is empty "<< endl;

    CURLcode ec = curl_easy_perform(m_curl);

    if(ec != CURLE_OK)
    {
        cout << "RunCurl Failed with " << curl_easy_strerror(ec)<<endl;
    }
    else
    {
        cout << "Successfully performed CURL request"<<endl;    
    }

    return ec;
}
/* client code */

CURLcode ec = CURLE_UNKNOWN_OPTION;    
CurlHelper* urlObj = new CurlHelper("www.google.com");
if((ec = urlObj.CurlRead(20)) != CURLE_OK)
{
    cout <<"Failed to set read curl options" << endl;
}
else if((ec = urlObj.RunCurl()) != CURLE_OK)
{
    cout <<"Failed to perform curl request" <<  endl;
}

现在,编译器在我传入的 userData 对象的 WriteCallback 中抛出 bad_alloc。我的目的是将获得的字节存储到 m_urlResponseData 中以供将来处理。

你能帮我理解这个问题吗?

按照 Wilx 的建议,我打印了 realSize 值,结果非常高,在这里找到了解决方案:http://curl.haxx.se/mail/lib-2009-04/0069.html

我已经相应地更改了代码,更改在 BOLD:

/* CurlHelper.hpp*/
**size_t WriteCallback(void * contents, size_t size, size_t nb);

static size_t WriteCallbackWrapper(void * contents, size_t size, size_t nb, void* thisPtr)
{
    if(thisPtr)
        return ((CurlHelper *)thisPtr)->WriteCallback(contents, size, nb);
    else
        return 0;
}**

/* CurlHelper.cpp*/
CURLcode CurlHelper::CurlRead(long timeout)
{
    CURLcode ec = CURLE_UNKNOWN_OPTION;

    if(!m_url.empty())
        cout << " m_url: " << m_url.c_str() << endl;

    if(m_curl)
    {
        **if(CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_WRITEFUNCTION, &CurlHelper::WriteCallbackWrapper))**
                && CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_NOPROGRESS, 1L))
                && CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_FOLLOWLOCATION, 1L))
                && **CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_WRITEDATA, this)**)
                && CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_TIMEOUT, timeout))
                && CURLE_OK == (ec = curl_easy_setopt(m_curl, CURLOPT_URL, m_url.c_str())))
        {
            cout << "Successfully set CURL Read options"<< endl;
        }
    }

    return ec;
}

size_t CurlHelper::WriteCallback(void * contents, size_t size, size_t nmemb)
{
    size_t realSize = size * nmemb;

    cout <<"realSize: " << realSize << endl;

    **try
    {
        m_urlResponseData.append(static_cast<const char *>(contents), realSize);
    }

    catch(bad_alloc& ba)
    {
        cerr<<"Failed: "<<ba.what() << endl;
        return 0;
    }**

    return realSize;
}