Curl使用字符串写回调会为用户数据抛出bad_alloc

时间:2015-02-01 10:46:53

标签: c++ string curl

我已经定义了一个像这样的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;
}

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

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

1 个答案:

答案 0 :(得分:0)

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