我试图将libcurl包装为辅助QObject类。不幸的是,我得到了一个神秘的段错误,当完全相同的代码放在一个类之外时不会发生。
示例代码:
//main.cpp
size_t writeCallback(char* ptr, size_t size, size_t nmemb, void* up)
{
size_t data_size = size * nmemb;
QByteArray *data = static_cast<QByteArray*>(up);
data->append(ptr, data_size);
return data_size;
}
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
QByteArray buffer;
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://cnn.com");
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
qDebug() << buffer;
return a.exec();
}
//Http.h
class Http : public QObject
{
Q_OBJECT
public:
Http();
void download();
signals:
void finished(const QByteArray &buffer);
private:
size_t writeCallback(char* ptr, size_t size, size_t nmemb, void* up);
};
//Http.cpp
Http::Http()
{
}
void Http::download()
{
QByteArray buffer;
CURL *curl;
CURLcode res;
curl = curl_easy_init();
if (curl) {
curl_easy_setopt(curl, CURLOPT_URL, "http://cnn.com");
/* example.com is redirected, so we tell libcurl to follow redirection */
curl_easy_setopt(curl, CURLOPT_FOLLOWLOCATION, 1L);
curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &Http::writeCallback);
curl_easy_setopt(curl, CURLOPT_WRITEDATA, &buffer);
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if (res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n",
curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
qDebug() << buffer;
emit finished(buffer);
}
size_t Http::writeCallback(char* ptr, size_t size, size_t nmemb, void* up)
{
size_t data_size = size * nmemb;
QByteArray *data = static_cast<QByteArray*>(up);
data->append(ptr, data_size); //<--SEGFAULTS
return data_size;
}
//main.cpp
int main(int argc, char *argv[]) {
QCoreApplication a(argc, argv);
Http http;
http.download();
return a.exec();
}
Http::writeCallback(char* ptr, size_t size, size_t nmemb, void* up)
==11246== Invalid read of size 1
==11246== at 0x4C2D7A2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11246== by 0x511EA14: QByteArray::append(char const*, int) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.0.1)
==11246== by 0x401B77: Http::writeCallback(char*, unsigned long, unsigned long, void*) (http.cpp:45)
==11246== by 0x4E48717: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x4E64A1B: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x4E5F8B1: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x4E68739: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x4E693D4: curl_multi_perform (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x4E60FDC: curl_easy_perform (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x401A45: Http::download() (http.cpp:26)
==11246== by 0x401838: main (main.cpp:57)
==11246== Address 0x1 is not stack'd, malloc'd or (recently) free'd
==11246==
==11246==
==11246== Process terminating with default action of signal 11 (SIGSEGV)
==11246== Access not within mapped region at address 0x1
==11246== at 0x4C2D7A2: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==11246== by 0x511EA14: QByteArray::append(char const*, int) (in /usr/lib/x86_64-linux-gnu/libQt5Core.so.5.0.1)
==11246== by 0x401B77: Http::writeCallback(char*, unsigned long, unsigned long, void*) (http.cpp:45)
==11246== by 0x4E48717: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x4E64A1B: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x4E5F8B1: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x4E68739: ??? (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x4E693D4: curl_multi_perform (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x4E60FDC: curl_easy_perform (in /usr/lib/x86_64-linux-gnu/libcurl.so.4.3.0)
==11246== by 0x401A45: Http::download() (http.cpp:26)
我完全失去了代码失败的原因。
PS。我知道这个示例代码是阻塞的,我知道有QNetworkAccessManager。我打算稍后将它移到QThread。我之所以使用libcurl,是因为我需要点击的网络服务与QNAM发送的默认标头不一致。