VS2013 ERROR 0xC0000005: when using libcurl

0

I'm trying to use libcurl (http://curl.haxx.se/libcurl/c/) for downloading data from a web, and store these data in a txt file , and here is my code:

// CLASS SinaStk

size_t save_data(char *buffer, size_t size, size_t nmemb, FILE* userdata){


locale loc = std::locale::global(std::locale("")); //TRY TO OPEN FILE WITH CHINESE

userdata = fopen(fpath.c_str(), "w");
if (userdata == NULL)
printf("File not open!\n");
locale::global(loc);
size_t writelen=size * nmemb;

fwrite(buffer, size, nmemb, userdata);

return writelen;
};

virtual void downloadUrl()   
{
    CURL* stkCURL=NULL;
    CURLcode res;
    FILE * fp=NULL;

    curl_global_init(CURL_GLOBAL_WIN32);  
    stkCURL = curl_easy_init();    

    curl_easy_setopt(stkCURL, CURLOPT_URL,"http://hq.sinajs.cn/list=s_sh000001"); 
    curl_easy_setopt(stkCURL, CURLOPT_WRITEFUNCTION, &SinaStk::save_data); 
    curl_easy_setopt(stkCURL, CURLOPT_WRITEDATA,fp);
    res=curl_easy_perform(stkCURL);                  //<-STOP!!!!

    fclose(fp);
    curl_easy_cleanup(stkCURL);
    curl_global_cleanup();
    return;
};

and when I debug my code, it always stop and then jump to xstring:

    size_type size() const _NOEXCEPT
    {   // return length of sequence
      return (this->_Mysize);                  // <-STOP!!! 
    }

0xC0000005: Access violation reading location 0x0000009E

I have no idea about the problem for almost a week. I am upset, I asked people around me and nobody knows why.

Thanks for reading, I am really confused.

=============

Problem is solved! Thanks you guys! now my code is:

//CLASS StkApiInfo
size_t writeData(char* buffer, size_t size, size_t nmemb){
    if (stkFile.is_open()){
        stkFile.close();
        stkFile.clear();
    };
    fpath = "D:\\Code\\代码\\数据文件\\" + fname + ".txt";
    stkFile.open(fpath.c_str(), ios::out);
    //if (stkFile.is_open())
    cout << buffer<<size<<nmemb;
    stkFile << buffer<<endl;
    stkFile.close();
    stkFile.clear();
    return size*nmemb;
};

//CLASS SinaStk : public StkApiInfo
static size_t save_data(char *buffer, size_t size, size_t nmemb, void* userdata){

    SinaStk* self = (SinaStk*)userdata;
    return self->writeData(buffer, size, nmemb);
};

virtual void downloadUrl()  
{
    CURL* stkCURL = NULL;
    CURLcode res;
    curl_global_init(CURL_GLOBAL_WIN32); 
    stkCURL = curl_easy_init();  
    if (stkCURL)
    {
        curl_easy_setopt(stkCURL, CURLOPT_URL, stkUrl.c_str());
        curl_easy_setopt(stkCURL, CURLOPT_WRITEFUNCTION, &SinaStk::save_data);
        curl_easy_setopt(stkCURL, CURLOPT_WRITEDATA, this);
        res = curl_easy_perform(stkCURL);
        //if (res != CURLE_OK)
        curl_easy_cleanup(stkCURL);
        curl_global_cleanup();
    }

    return;
};
c++
visual-studio
libcurl
asked on Stack Overflow May 16, 2015 by noxeve • edited May 16, 2015 by noxeve

1 Answer

1

Callback passed with CURLOPT_WRITEFUNCTION argument should be of type write_callback (with exact that signature) and therefore cannot be non-static class method. Usual workaround is to define callback as non-member or static method and pass this as an argument:

static size_t save_data(char *buffer, size_t size, size_t nmemb, void* userdata)
{
    SinaStk* self = (SinaStk*) userdata;
    return self->doStuff(buffer, size, nmemb);
}

virtual void downloadUrl()   
{
    //...
    curl_easy_setopt(stkCURL, CURLOPT_WRITEFUNCTION, &SinaStk::save_data); 
    curl_easy_setopt(stkCURL, CURLOPT_WRITEDATA, this);
    //...
}

If you need to access additional data (like FILE* in your example) you can either store it as class field or introduce temporary structure that would contain this and additional data fields and pass it's address as callback argument.

answered on Stack Overflow May 16, 2015 by dewaffled • edited May 16, 2015 by Remy Lebeau

User contributions licensed under CC BY-SA 3.0