2012-06-09 3 views
2

업데이트-2런타임 오류 : "*** glibc는 감지 *** : 더블 무료 또는 손상 (교체 아웃)"

내가 경고 & 오류의 흥미로운 조합이있다.

QIODevice::open: File access not specified 

과 순간적으로

*** glibc detected *** <path>: double free or corruption (out): 0x081f9d00 *** 

가 여기에 원인이되는 최소한의 코드입니다 : 내가 런타임 오류가, 둘째

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' 

: 디버깅 할 때

첫째, 내가 경고를 얻을 오류 (최소화했습니다) :

결과 폴더 생성 된 폴더 "자원"으로하고 "vk.cookie"(따옴표없이 모든) 파일에서개

파일

.

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" 

여기에 메모리 덤프와 최대 출력입니다 : http://pastebin.com/btVNe4nd

,369가 (: 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 ** 

외 1 5 QtCreator에서 1,363,210

앱은 OS로부터 수신 신호를 말한다 맡은 일. writeCookies()에서 각 코드 행 다음에 qDebug() 출력을 추가하고 실행 (디버그가 아닌) 모드에서 프로그램을 실행하면 모두 출력이 출력됩니다. 그래서 문제는 일부 Qt 클래스 소멸자에 있습니다.(code with qDebug output)

왜 그런 오류가 발생합니까?

+4

[최소 테스트 케이스] (http://sscce.org)를 작성하십시오. –

+0

@OliCharlesworth done. –

+0

어떤 운영 체제입니까? – cmannett85

답변

3

귀하의 문제는 setCookieJar() 상태에 대한

messagesPage->page()->networkAccessManager()->setCookieJar(&jar); 

문서 라인에 있습니다

delete cookieJar; 
다음 QNetworkAccessManager가 파괴됩니다 때, 그것은 다음과 같은 코드를 실행된다는 것을 의미합니다

Note: QNetworkAccessManager takes ownership of the cookieJar object. 

이 경우 다음을 유의하십시오.

  1. 는 스택 할당 jar 당신이 setCookieJar에 전달이 사라 졌어요. 네트워크 관리자는 손상된 쿠키 항아리에 액세스하여 물건을 손상시킬 가능성이 큽니다. newAuthoriseRequest()이 종료되자 마자 파괴되었습니다. 네트워크 관리자는 별도의 스레드에서 일부 기능을 실행할 수 있습니다.

  2. 이 아니고 을 통해 힙에 직접 할당 된이 아닌 개체에서 삭제가 시도됩니다.

단순히

QPointer<QNetworkCookieJar> jar; 

에 선언을 변경하고 새 QWebView을 만들 때마다 새로운 쿠키 항아리를 할당합니다.

QPointer를 사용하면 QWebView의 네트워크 액세스 관리자가 삭제 한 쿠키 항아리에 매달려있는 포인터를 사용하지 못하게됩니다. 실수로 포인터를 사용하려고 시도하면 포인터가 이미 0으로 재설정되고 포인터를 역 참조하려고하는 행에서 즉시 segfault가 표시됩니다. 그것은 쉽게 디버깅 할 수 있습니다.

중요한 실수은 자급 자족 한 예를 최소화하기 위해 중단되었습니다. 당신이 그것을 지켰다면 다음 10 분에서 15 분 안에 문제를 발견했을 것입니다.

#include <QtGui/QApplication> 
#include <QtWebKit/QWebView> 
#include <QtNetwork/QNetworkCookieJar> 
#include <QtCore/QList> 

int main(int argc, char *argv[]) { 
    QApplication a(argc, argv); 
    QWebView * view = new QWebView(); 
    QNetworkCookieJar jar; 
    QList<QNetworkCookie> cookies; 
    jar.setCookiesFromUrl(cookies, QUrl("http://google.com")); 
    view->page()->networkAccessManager()->setCookieJar(&jar); 
    view->load(QUrl("http://www.google.com")); 
    view->show(); 
    view->connect(view, SIGNAL(loadFinished(bool)), SLOT(deleteLater())); 
    a.exec(); 
} 

숙제가 : QPointer, QScopedPointer, QSharedPointer 및 QWeakPointer에 읽어

는이 문제를 재현 최소한의 예입니다. 그것들은 매우 유용하며, 대부분의 경우 코드에서 클래스 멤버로서 누드 포인터를 사용하는 것은 버그 발생을 기다리고 있습니다. QWidgets와 같은 자식 QObject (부모의 수명과 일치하는 수명을 제외하고) 즉 그들은 부모가 죽을 때에 만 죽는다).

+0

감사합니다. –

관련 문제