PDA

View Full Version : runtime error: “*** glibc detected ***: double free or corruption (out)”



gxoptg
10th June 2012, 13:18
I have interesting combination of warnings & errors.

Firstly, when debugging, i get warnings:


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'
secondly, i have runtime error:


QIODevice::open: File access not specified
and momently


*** glibc detected *** <path>: double free or corruption (out): 0x081f9d00 ***
Here's the minimal code that causes that errors:

Files

In result folder created folder "resources" and in it file "vk.cookie" (everything without quotes).

Bug.pro


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

printer.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

printer.cpp


#include "printer.h"

Here's the full output with memory dump: http://pastebin.com/btVNe4nd

At 5 QtCreator says that app received signal from OS (signal: SIGABRT) and decompiles


Disassembler (__kernel_vsyscall)

0x132414 <+0x0000> int $0x80
0x132416 <+0x0002> ret

And valgrind says:


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 **

Question on StackOwerflow: http://stackoverflow.com/questions/10963267/runtime-error-glibc-detected-double-free-or-corruption-out

So, why I receive they? I don't use malloc()/free(), you can see it.

ChrisW67
11th June 2012, 02:23
Point 5. Line 101 of api_vk.cpp should specify QIODevice::WriteOnly

The other Web Kit related warnings do not appear on my Linux build and do not seem related to the real problem.

You are using malloc or a similar function, just not directly. You get double free because you create a QNetworkCookieJar instance as a member and pass a pointer to the QNetworkAccessManager (QNAM) underlying the web view. As the docs for QNetworkAccessManager::setCookieJar() tell you:


Note: QNetworkAccessManager takes ownership of the cookieJar object.

So, the cookie jar member variable is destroyed when it goes out of scope and the QNAM will also try to delete the cookie jar when the QNAM is destroyed by your deleteLater() call. Double-free == Boom!

I am not sure why you have created a QNetworkCookieJar of your own anyway. QNAM has one by default and you are not passing a customised version in order to implement persistence (you do that outside the cookie jar object). To keep your implementation more-or-less intact make jar a local QNetworkCookieJar*, initialise it using QNetworkAccessManager::cookieJar(), and load the cookies into the existing instance.

Alternatively, you could create a QNetworkCookieJar subclass that handles its own persistence. During initialisation you allocate a custom cookie jar class on the heap, set it on the QNAM, and let the QNAM handle deletion.