c++ - 运行时错误: "*** glibc detected ***: double free or corruption (out)"

标签 c++ qt io runtime-error glibc

更新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”(所有内容均不带引号)。

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

ma​​in.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

打印机.cpp

#include "printer.h"

这是内存转储的完整输出:http://pastebin.com/btVNe4nd

在 5 点,QtCreator 表示应用程序收到了来自操作系统的信号(信号: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 类析构函数中。 (code with qDebug output)

那么,为什么我会收到这些错误?

最佳答案

你的问题就在这行

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

setCookieJar() 的文档指出:

Note: QNetworkAccessManager takes ownership of the cookieJar object.

这意味着当QNetworkAccessManager被销毁时,它将执行以下代码:

delete cookieJar;

请注意,当发生这种情况时:

  1. 您传递给 setCookieJar 的堆栈分配 jar 早已不复存在。网络管理员很可能通过访问被破坏的 cookie jar 来破坏东西——一旦 newAuthoriseRequest() 退出,它就被破坏了。请记住,网络管理器可以在单独的线程中运行其某些功能。

  2. 尝试删除通过new直接在堆上分配的对象。

只需将声明更改为

QPointer<QNetworkCookieJar> jar;

并在每次创建新的QWebView时分配一个新的cookie jar。

使用 QPointer 将防止您尝试使用指向已被 QWebView 的网络访问管理器删除的 cookie jar 的悬空指针。如果您错误地尝试使用它,则指针将已重置为零,并且您将在尝试取消引用指针的行处立即出现段错误。这很容易调试。

您的主要错误是停止进一步最小化您的独立示例。如果您坚持下去,您会在接下来的 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。它们非常有用,在大多数情况下,您会发现在代码中使用裸指针作为类成员是一个等待发生的错误,除了子 QObject(例如 QWidget),其生命周期与其父级的生命周期相匹配(即,只有当 parent 去世时,他们才会死亡)。

关于c++ - 运行时错误: "*** glibc detected ***: double free or corruption (out)",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10963267/

相关文章:

qt - 在 Qt 中创建旋转进度条

go - scanner.Scan() 在 Linux 但不是 Windows 上阻塞直到退出

c++ - 对于 OpenGL 着色器,您将如何在 C++ 中编写接受所有类型的统一函数?

c++ - 终止处理程序可以抛出异常吗?

visual-studio - Qt 5.8 msvc 2015 编译错误

c++ - 融合样式不适用于 QTabWidget 中的 QTextBrowser

linux - 获取一段时间内目录中所有文件系统操作的计数

windows - PowerShell,不包含方法 'items'

c++ - 什么比 std::pow 更快?

c++ - 使用 C++ 的 RGB 到 CMY 颜色模型