【问题标题】:libcurl/cURL c++ segfaultlibcurl/cURL c++ 段错误
【发布时间】:2012-11-24 00:35:53
【问题描述】:

我正在尝试编写一个类以使用 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] 的调用中中断)。任何帮助表示赞赏

【问题讨论】:

  • 你测试过buf == this吗?
  • 这是我应该担心的事情吗?据我所知buf 是通过网络调用传入的;它基本上应该是来自网站的数据。
  • 我的意思是,对于 C++ 类方法,this 可以被认为是静态 C 风格函数的隐式第一个参数。如果 curl 调用你提供的回调,就好像它是一个 C 风格的函数(它是),至少调用约定不像 C++ 在调用时在类方法中所期望的那样,并且会发生未定义的事情。

标签: c++ curl


【解决方案1】:

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

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

现在,curl_easy_setopt 并不在乎——它会接受你给它的任何东西。但是当它调用这个函数时,坏事就会发生。

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

【讨论】:

  • 不幸的是,curl_easy_setopt 是一个可变参数函数,因此无法检查函数参数的类型是否正确——否则,编译器肯定会给出无法转换 @ 的错误987654332@ 到size_t (*)(char*, size_t, size_t, void*)
【解决方案2】:

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

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

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

【讨论】:

    猜你喜欢
    • 2016-04-14
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 2019-05-25
    • 2017-05-24
    • 2020-11-07
    • 2016-12-18
    • 1970-01-01
    相关资源
    最近更新 更多