noxeve
noxeve

Reputation: 31

VS2013 ERROR 0xC0000005: when using libcurl

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

Upvotes: 0

Views: 680

Answers (1)

dewaffled
dewaffled

Reputation: 2963

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.

Upvotes: 1

Related Questions