libcurl / cURL c ++段错误

时间:2012-11-24 00:35:53

标签: c++ curl

我正在尝试编写一个类来使用cURL从C ++网站获取一些数据。这是来自该类的示例(有一个Curl * curl_数据成员,rawData_是一个字符串)。这段摘录来自实现文件,所有函数都在标题中声明。

MyClass::MyClass()
{
    curl_global_init(CURL_GLOBAL_ALL);
    curl_ = curl_easy_init();

    curl_easy_setopt(curl_, CURLOPT_URL,
               "http://www.google.com");
    curl_easy_setopt(curl_, CURLOPT_WRITEFUNCTION, &MyClass::writeCallback);

}

MyClass::~MyClass()
{
    curl_easy_cleanup(curl_);
    curl_global_cleanup();
}

size_t MyClass::writeCallback(char* buf, size_t size, size_t nmemb, void* up)
{
    //buf is a pointer to the data that curl has for us
    //size*nmemb is the size of the buffer
    for (size_t c = 0; c<size*nmemb; ++c)
    {
        cerr << c << endl;
        rawData_.push_back(buf[c]);
    }
    return size*nmemb; //tell curl how many bytes we handled
}

void MyClass::makeCall()
{
    curl_easy_perform(curl_);
}

当我创建MyClass的实例并调用makeCall时,writeCallBack函数中存在段错误。也就是说,buf似乎大小为0(当c = 0时,它在buf [c]的调用时中断)。任何帮助表示赞赏

2 个答案:

答案 0 :(得分:4)

curl_easy_setopt CURLOPT_WRITEFUNCTION的参数应为size_t function( char *ptr, size_t size, size_t nmemb, void *userdata)类型。这是一个“干净”的C函数,而不是一种方法。

但据我所知,您传递的是非静态方法的地址。所以它没有正确的签名(我猜它是非静态的,因为你在里面使用rawData_。)

现在,curl_easy_setopt并不在乎 - 它需要你付出的任何东西。但是当它调用函数时会发生不好的事情。

我的建议是将writeCallback声明为静态(或甚至是非会员朋友)并将用户数据设置为this(使用curl_easy_setopt CURLOPT_WRITEDATA) 。然后,您可以将userdata参数强制转换为MyClass并在函数内使用它。

答案 1 :(得分:0)

在解释curl_easy_setopt的libcurl联机帮助页CURLOPT_WRITEFUNCTION中,它指出在某些情况下可以使用“零大小”调用回调,例如指示空响应。在这种情况下,至少size*nmemb的乘积应为零,因此您的循环永远不会输入空缓冲区,因此您应该在那里安全。

但是,它还将CURLOPT_WRITEFUNCTION的参数描述为使用给定参数的函数,而不是C ++成员函数。很可能是回调成员函数体中的隐式this指针被解释为buf。恰好,this(内部类状态)第一次在与崩溃相同的行中被取消引用:rawData_.push_back(buf[c])

快速,尝试将您的类成员函数回调转换为静态函数回调(即,不再是MyClass的成员)。这应该工作。然后,您可以将此函数用作friendMyClass,或者如果将适当的this指针传递给CURLOPT_WRITEDATA,则可以代理对类成员函数的调用。使用curl_easy_setopt设置回调时的选项,允许静态非成员函数使用指向类对象的相应指针调用相应的C ++类方法。