更新-2
警告とエラーの興味深い組み合わせがあります。
まず、デバッグ時に警告が表示されます。
can't find linker symbol for virtual table for `QFile' value
found `WebCore::JSDocument::JSDocument(JSC::Structure*, WebCore::JSDOMGlobalObject*, WTF::PassRefPtr<WebCore::Document>)' instead
RTTI symbol not found for class 'WebCore::JSHTMLDocument'
RTTI symbol not found for class 'WebCore::JSHTMLDocument'
RTTI symbol not found for class 'WebCore::JSHTMLDocument'
次に、実行時エラーがあります:
QIODevice::open: File access not specified
そして一瞬
*** glibc detected *** <path>: double free or corruption (out): 0x081f9d00 ***
そのエラーの原因となる最小限のコードは次のとおりです(最小化しました):
ファイル
結果フォルダーに作成されたフォルダー「resources」とそのファイル「vk.cookie」(引用符なしのすべて)。
バグプロ
QT += core gui webkit network xml
TARGET = Bug
TEMPLATE = app
SOURCES += main.cpp \
api_vk.cpp \
printer.cpp
HEADERS += \
api_vk.h \
printer.h
main.cpp
#include <QtGui/QApplication>
#include "api_vk.h"
#include "printer.h"
int main(int argc, char *argv[]) {
QApplication a(argc, argv);
API_VK *apivk = new API_VK;
apivk->authorise();
Printer *printer = new Printer;
QObject::connect(apivk, SIGNAL(authorisationSucceed()), printer, SLOT(printOK()));
QObject::connect(apivk, SIGNAL(authorisationFailed(QString,QString)), printer, SLOT(printFail()));
return a.exec(); }
api_vk.h
#ifndef API_VK_H
#define API_VK_H
#include <QObject>
#include <QTimer>
#include <QUrl>
#include <QtNetwork/QNetworkCookieJar>
class QWebView;
class QString;
class QNetworkReply;
class QXmlInputSource;
class QTimer;
class QNetworkCookie;
class API_VK : public QObject
{
Q_OBJECT
public:
explicit API_VK(QObject *parent = 0);
signals:
void authorisationFailed(QString error, QString error_description);
void authorisationSucceed();
public slots:
void authorise();
protected:
void readCookies();
void writeCookies();
protected slots:
void newAuthoriseRequest();
void processUrl(QUrl url);
private:
static const QString app_id;
static QString access_token;
static qint32 expires_in;
QWebView *messagesPage;
QList<QNetworkCookie> cookies;
QNetworkCookieJar jar;
static bool authorised;
};
#endif
api_vk.cpp
#include "api_vk.h"
#include <QtGui>
#include <QWebView>
#include <QtNetwork/QNetworkRequest>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkCookie>
#include <QtNetwork/QNetworkCookieJar>
#include <QString>
#include <QStringList>
#include <QFile>
#include <QTextStream>
#include <QTimer>
#include <QUrl>
#include <QtXml>
#include <QVariant>
#include <QDateTime>
#include <QDebug>
bool API_VK::authorised = false;
const QString API_VK::app_id = "2783286";
QString API_VK::access_token = "";
int API_VK::expires_in = 0;
// defining class methods
API_VK::API_VK(QObject *parent) :
QObject(parent)
{
}
void API_VK::authorise() {
newAuthoriseRequest(); // 1. going here
}
void API_VK::newAuthoriseRequest() {
// gets new access_token
// 2. going here
messagesPage = new QWebView;
readCookies();
jar.setCookiesFromUrl(cookies, QUrl("http://vk.com"));
messagesPage->page()->networkAccessManager()->setCookieJar(&jar);
QUrl url("http://oauth.vk.com/authorize");
url.addQueryItem("client_id", app_id);
url.addQueryItem("scope", "messages");
url.addQueryItem("redirect_uri","http://api.vk.com/blank.html");
url.addQueryItem("display","page");
url.addQueryItem("response_type","token");
messagesPage->load(QNetworkRequest(url));
connect(messagesPage, SIGNAL(urlChanged(QUrl)), this, SLOT(processUrl(QUrl)));
messagesPage->show();
}
void API_VK::processUrl(QUrl url) { // 3. going here
/* firstly we're here when oath.vk.com redirects us to api.vk.com/login...
* in this case we're exiting at 4.
* secondly, user logs in, and api.vk.com/login redirects us back to oath.vk.com,
* where we get access_token, etc
* and when debugging, we start receiving warnings about "can't find linker symbol" secondly, not firstly
*/
// if (!url.hasQueryItem("access_token"))
// return;
/* I commented previous part because most of you doesn't have VK accounts so you can't go
* to the next part of code */
access_token = url.queryItemValue("access_token");
expires_in = url.queryItemValue("expires_in").toInt();
emit authorisationSucceed();
authorised = true;
cookies = messagesPage->page()->networkAccessManager()->cookieJar()->cookiesForUrl(QUrl("http://vk.com"));
messagesPage->deleteLater();
writeCookies();
}
void API_VK::readCookies() {
QFile file("./resouces/vk.cookie");
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
return;
}
QTextStream in(&file);
QByteArray name, value;
while (!in.atEnd()) {
in >> name >> value;
cookies.append(QNetworkCookie(name, value));
}
}
void API_VK::writeCookies() {
QFile file("./resouces/vk.cookie"); // note: this file exists
if (!file.open(QIODevice::Truncate | QIODevice::Text)) { // 5. at this line i receive runtime errors
return;
}
QTextStream out(&file);
for (QList<QNetworkCookie>::const_iterator i = cookies.begin(); i != cookies.end(); ++i) {
out << (*i).name() << ' ' << (*i).value() << '\n';
}
}
プリンター.h
#ifndef PRINTER_H
#define PRINTER_H
#include <QObject>
#include <QDebug>
struct Printer: public QObject {
Q_OBJECT
public slots:
void printOK() { qDebug() << "OK"; }
void printFail() { qDebug() << "Fail"; }
};
#endif // PRINTER_H
プリンター.cpp
#include "printer.h"
メモリ ダンプを含む完全な出力は次のとおりです: http://pastebin.com/btVNe4nd
5 で QtCreator は、アプリが OS からシグナルを受信したと言い (シグナル: SIGABRT)、逆コンパイルします。
逆アセンブラー (__kernel_vsyscall)
0x132414 <+0x0000> int $0x80
0x132416 <+0x0002> ret
そして、valgrind は次のように述べています。
Analysis of memory <path>
QMetaObject::connectSlotsByName: No matching signal for on_cancelButton_clicked()
"sni-qt/23102" WARN 20:28:53.697 void StatusNotifierItemFactory::connectToSnw() Invalid interface to SNW_SERVICE
** Analysis finished **
** Unknown error **
後もう一つ。writeCookies() の各コード行の後に qDebug() 出力を追加し、実行 (デバッグではない) モードでプログラムを起動すると、この出力がすべて出力されました。したがって、問題は Qt クラスのデストラクタにあります。( qDebug出力を含むコード)
では、なぜそのエラーが表示されるのでしょうか?