简体   繁体   English

libcurl C++ 的内存访问错误

[英]Memory access error with libcurl C++

I am trying to make a very simple program that get a user request (console) and send this request to a website in the headers (libcurl) and then get the response headers.我正在尝试制作一个非常简单的程序,它获取用户请求(控制台)并将此请求发送到标头(libcurl)中的网站,然后获取响应标头。

So I have 2 classes (in fact I got a lot of classes but for the problem here I will simplify)所以我有 2 个类(实际上我有很多类,但对于这里的问题,我会简化)

My main.cpp get the request and send it to my service.我的 main.cpp 收到请求并将其发送到我的服务。

So here is my service Fuzzer.h :所以这是我的服务 Fuzzer.h :

#ifndef FUZZER_H
#define FUZZER_H

#include <string>

using namespace std;

namespace furez 
{
    class Fuzzer {
    private:
        string url;
        string response;
        static size_t writeH_static(void *, size_t, size_t, void *);

    public:
        Fuzzer(string);
        virtual ~Fuzzer();
        string sendRequest(string);
        size_t writeH(void *, size_t, size_t);
    };

}

#endif

and here is my Fuzzer.cpp:这是我的 Fuzzer.cpp:

#include <string>
#include <curl/curl.h>
#include <iostream>

#include "Fuzzer.h"

namespace furez 
{
    Fuzzer::Fuzzer(std::string u) 
    {
        this->url = u;
    }

    Fuzzer::~Fuzzer(){}

    string Fuzzer::sendRequest(std::string request) 
    {
        CURL *curl;
        CURLcode res;

        static const char *headerfilename = "head.out";
        static const char *bodyfilename = "body.out";

        curl = curl_easy_init();
        if (curl) {
            struct curl_slist *chunk = NULL;

            chunk = curl_slist_append(chunk, "Accept:");
            chunk = curl_slist_append(chunk, "Another: yes");
            chunk = curl_slist_append(chunk, "Host: example.com");
            chunk = curl_slist_append(chunk, "X-silly-header;");

            curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &Fuzzer::writeH);

            Fuzzer instance(request);
            curl_easy_setopt(curl, CURLOPT_WRITEDATA, &instance);

            curl_easy_setopt(curl, CURLOPT_URL, "localhost");

            res = curl_easy_perform(curl);
            /* Check for errors */
            if (res != CURLE_OK) {
                fprintf(stderr, "curl_easy_perform() failed: %s\n",
                    curl_easy_strerror(res));
            }

            curl_easy_cleanup(curl);
            curl_slist_free_all(chunk);
        }

        return request;
    }

    size_t Fuzzer::writeH_static(void *ptr, size_t size, size_t nmemb, void *stream)
    {
        return ((Fuzzer*)stream)->writeH(ptr, size, nmemb);
    }

    size_t Fuzzer::writeH(void *ptr, size_t size, size_t nmemb)
    {
        //std::string str = (CHAR *)ptr;
        //std::string str2("Server:");

        //if (str.find(str2) != string::npos) {
            //this->response = str;
        //}

        size_t realsize = size * nmemb;
        return realsize;
    }
}

But when I try to execute this I got an Memory error.但是当我尝试执行此操作时,出现内存错误。 Because of this:因为这:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &Fuzzer::writeH);

I am using libcurl for my project.我正在为我的项目使用 libcurl。 I know that it's a C library maybe it's the problem?我知道它是一个 C 库,也许这是问题所在?

In order to help me I followed theses instructions: libcurl callbacks w/c++ class members为了帮助我,我遵循了这些说明: libcurl callbacks w/c++ class members

and this one: curl WRITEFUNCTION and classes I'm on Windows 7 and got Visual Studio 2013.还有这个: curl WRITEFUNCTION 和 classes我在 Windows 7 上并获得了 Visual Studio 2013。

(PS: When I put this code without &Fuzzer::writeH and static function inside main.cpp it works without any problem.) (PS:当我在 main.cpp 中放置没有 &Fuzzer::writeH 和静态函数的代码时,它可以正常工作。)

I think the issue is here:我认为问题出在这里:

curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &Fuzzer::writeH);

as you correctly stated, libcurl is a C library, but you are passing to the function curl_easy_setopt a pointer to member function.正如您正确指出的那样,libcurl 是一个 C 库,但是您正在向函数curl_easy_setopt传递一个指向成员函数的指针。 Now, funtion pointers and pointer to members of a class are different types, so, you cannot do that.现在,函数指针和指向类成员的指针是不同的类型,因此您不能这样做。 The only solution I'm aware of is using a trampoline call .我知道的唯一解决方案是使用trampoline call

  • Create a plain function (non member of your class) that you will register as the callback in the curl_easy_setopt()创建一个普通函数(非类的成员),您将在 curl_easy_setopt() 中将其注册为回调
  • make the trampoline callback friend of your class (so she might access the private members if needed)让蹦床回调成为你班级的朋友(这样她就可以在需要时访问私人成员)
  • The userdata argument passed to the callback should be the pointer to your class传递给回调的userdata参数应该是指向您的类的指针
  • inside the trampoline callback you will cast the pointer back to your class and call the desired member function(s)在蹦床回调中,您将指针转换回您的类并调用所需的成员函数

As an example:举个例子:

extern "C" size_t trampolineCallback( char * i_buffer, size_t i_size, size_t i_nitems, void * i_userdata );

In your class implementation you will have something like:在您的类实现中,您将拥有以下内容:

curl_easy_setopt( m_curlHndlPtr, CURLOPT_HEADERDATA, (void*) this );
curl_easy_setopt( m_curlHndlPtr, CURLOPT_HEADERFUNCTION, trampolineCallback );

Your trampoline implementation will look like:您的蹦床实现将如下所示:

size_t trampolineCallback(char *i_buffer, size_t i_size, size_t i_nitems, void *i_userdata)
{
    MyObj * object = (MyObj*) i_userdata;
    object->myMemberFunc( i_buffer,i_size, i_nitems );
    return (i_size * i_nitems);
}

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

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