环境:
系统:Windows 8专业版(32位)
IDE:VS 2013
curl库版本:libcurl-7.19.3-win32-ssl-msvc
运行时提示
0x61DE35F7 (curllib.dll) (curltest.exe 中)处有未经处理的异常: 0xC0000005: 读取位置 0xFEEEFF02 时发生访问冲突。
#include "stdafx.h"
#include "curl/curl.h"
#include <iostream>
#include <fstream>
#include <sstream>
#include <string>
#include <vector>
#include <io.h>
#pragma comment(lib, "curl/libcurl_imp.lib")
#define PROGNAME "curltest"
#define RETRY_TIME 5
#define URL_SIZE 100
using namespace std;
size_t print_callback(char* buffer, size_t size, size_t nitems, void *outstream)
{
return nitems;
}
size_t write_callback(char* buffer, size_t size, size_t nitems, string &text)
{
size_t sizes = size * nitems;
string temp(buffer, sizes);
text += temp;
return sizes;
}
int progress_callback(void *clientp, double dltotal, double dlnow, double ultotal, double ulnow)
{
printf("%.1f%%\t", 100 * (dlnow / dltotal));
cout << "\r";
cout.flush();
return 0;
}
class Novel
{
private:
CURL *eh;
CURLcode res;
int http_code;
int retry_time;
public:
int id;
double filesize;
bool is_exist;
char *url = new char[URL_SIZE];
string *text = new string;
Novel(int id)
{
this->id = id;
retry_time = RETRY_TIME;
sprintf_s(url, URL_SIZE, "dl.wenku8.cn/down.php?type=txt&id=%d", id);
eh = curl_easy_init();
curl_easy_setopt(eh, CURLOPT_URL, url);
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, print_callback);
curl_easy_setopt(eh, CURLOPT_NOPROGRESS, 1);
curl_easy_setopt(eh, CURLOPT_PROGRESSFUNCTION, progress_callback);
curl_easy_setopt(eh, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(eh, CURLOPT_HEADER, 1);
curl_easy_setopt(eh, CURLOPT_NOBODY, 1);
res = curl_easy_perform(eh);
curl_easy_getinfo(eh, CURLINFO_HTTP_CODE, &http_code);
if (http_code == 404)
{
is_exist = false;
filesize = -1;
return;
}
else
is_exist = true;
curl_easy_getinfo(eh, CURLINFO_CONTENT_LENGTH_DOWNLOAD, &filesize);
}
int start()
{
if (is_exist == false)
{
cerr << "文件不存在" << endl;
return 1;
}
else
{
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(eh, CURLOPT_NOBODY, 0);
curl_easy_setopt(eh, CURLOPT_HEADER, 0);
curl_easy_setopt(eh, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(eh, CURLOPT_WRITEDATA, text);
cout << "正在下载 " << id << ".txt" << endl;
res = curl_easy_perform(eh);
if (res != CURLE_OK)
{
cerr << curl_easy_strerror(res) << endl;
return -1;
}
cout << "下载完成" << endl;
}
return 0;
}
~Novel()
{
curl_easy_cleanup(eh);
delete[] url;
delete text;
}
};
int main(int argc, char *argv[])
{
/*
int retry_time = RETRY_TIME;
int id = 1;
vector<Novel> vNovel;
for (id = 1; retry_time!=0; id++)
{
vNovel.push_back(id);
if (vNovel[id - 1].start())
{
retry_time--;
}
else
{
retry_time = RETRY_TIME;
}
}
getchar();
vNovel.clear(); // 这句出错
*/
// 上面是出错的地方,下面无错
Novel test(1);
test.start();
getchar();
return 0;
}
该回答引用ChatGPT
问题出在vector中存储了Novel对象,但是Novel类中没有实现拷贝构造函数和赋值运算符重载函数,所以在vector调用元素复制时出错。可以通过实现拷贝构造函数和赋值运算符重载函数解决这个问题。
在Novel类中添加以下代码:
Novel(const Novel& other) //拷贝构造函数
{
id = other.id;
filesize = other.filesize;
is_exist = other.is_exist;
url = new char[URL_SIZE];
strcpy_s(url, URL_SIZE, other.url);
text = new string;
*text = *other.text;
eh = curl_easy_init();
curl_easy_setopt(eh, CURLOPT_URL, url);
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(eh, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(eh, CURLOPT_PROGRESSFUNCTION, progress_callback);
curl_easy_setopt(eh, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(eh, CURLOPT_HEADER, 0);
curl_easy_setopt(eh, CURLOPT_NOBODY, 0);
curl_easy_setopt(eh, CURLOPT_WRITEDATA, text);
}
Novel& operator=(const Novel& other) //赋值运算符重载函数
{
if (this != &other)
{
id = other.id;
filesize = other.filesize;
is_exist = other.is_exist;
delete[] url;
url = new char[URL_SIZE];
strcpy_s(url, URL_SIZE, other.url);
delete text;
text = new string;
*text = *other.text;
curl_easy_cleanup(eh);
eh = curl_easy_init();
curl_easy_setopt(eh, CURLOPT_URL, url);
curl_easy_setopt(eh, CURLOPT_WRITEFUNCTION, write_callback);
curl_easy_setopt(eh, CURLOPT_NOPROGRESS, 0);
curl_easy_setopt(eh, CURLOPT_PROGRESSFUNCTION, progress_callback);
curl_easy_setopt(eh, CURLOPT_FOLLOWLOCATION, 1);
curl_easy_setopt(eh, CURLOPT_HEADER, 0);
curl_easy_setopt(eh, CURLOPT_NOBODY, 0);
curl_easy_setopt(eh, CURLOPT_WRITEDATA, text);
}
return *this;
}
这样,在Novel类中就实现了拷贝构造函数和赋值运算符重载函数,可以避免vector调用元素复制时出错。另外,可以通过加入move构造函数和move赋值运算符重载函数进一步优化代码。