如果安装在单独的类上,Qt Message Handler会崩溃吗?

时间:2016-01-08 07:03:19

标签: c++ qt

每当有消息发送到我的自定义消息处理程序时,它会通过分段错误错误使标记行处的应用程序崩溃。

// main.cpp

void myMessageOutput(QtMsgType type, const QMessageLogContext &context, const QString &msg)
{
    QStringList data;
    data.append(context.category);
    data.append(context.file);
    data.append(context.function);
    data.append(QString(context.line));
    data.append(QString(context.version));
    Logger::get_obj()->myMessageOutput(type, data, msg);
}

int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
    a.setApplicationName("MyApp");
    a.setWindowIcon(QIcon(":/Icons/MyApp.png"));

    Logger log;
    qInstallMessageHandler(myMessageOutput);
    log.turnOnDebug();

    MySplashScreen splash;
    splash.show();
    a.processEvents();

...

    splash.close();
    MainWindow *w = new MainWindow();

    int errorCode = a.exec();
    delete w;
    session.destruct();
    qDebug() << "\n*** Application exited with error code " << errorCode << " ***";
    return errorCode;
}
// logger.h

#ifndef LOGGER_H
#define LOGGER_H

#include <QObject>
#include <QFile>
#include <QTextStream>
#include <QMutex>

class Logger : public QObject
{
    Q_OBJECT
public:
    void myMessageOutput(QtMsgType type, QStringList context, const QString msg);
    explicit Logger(QObject *parent = 0);
    ~Logger();
    static Logger *get_obj() {return ptr;}
    static void turnOnDebug() {get_obj()->debugMode = true;}
    static void turnOffDebug() {get_obj()->debugMode = false;}
    static void moveLogToSession(QString sessionName);

private:
    QFile *logFile;
    QTextStream *stream;
    QMutex *mutex;
    bool debugMode;
    bool errorMsg;
    static Logger *ptr;

    void write(QString str);

signals:
    void SaveSession();
    void FatalSaveSession();

public slots:

};

#endif // LOGGER_H
// logger.cpp

#include <QDir>
#include <QFile>
#include <QMessageBox>
#include <QApplication>
#include "logger.h"
#include "systemvariables.h"

Logger *Logger::ptr = NULL;

Logger::Logger(QObject *parent) : QObject(parent)
{
    logFile = NULL;
    stream = NULL;
    mutex = NULL;
    debugMode = false;
    errorMsg = false;

    ptr = this;
    QString path = SystemVariables::getAppData();
    QDir dir = QDir(path);
    if(dir.exists())
    {
        path.append("/MyApp/Logs");
        dir = QDir(path);
        if(!dir.exists())
            dir.mkpath(path);

        logFile = new QFile(path + "/Session.log");
        if(logFile->exists())
            logFile->remove();

        if(!logFile->open(QFile::WriteOnly | QFile::Text))
        {
            qFatal("Could not create log file.");
        }

        stream = new QTextStream(logFile);
        stream->setRealNumberNotation(QTextStream::SmartNotation);
        stream->setRealNumberPrecision(15);
        *stream << "*** MyApp Session Begins ***\n";
    }
    else
        qFatal("Could not create log file.");

    mutex = new QMutex();
}

void Logger::myMessageOutput(QtMsgType type, QStringList context, const QString msg)
{
   mutex->lock();
   QString str = "";
    switch (type)
    {
        case QtDebugMsg:
        if(!debugMode)
        {
            mutex->unlock();
            return;
        }
        write(msg);
        break;

        case QtInfoMsg:
        str.append("\n*** Information ***\n");
        str.append(msg + "\n");
        str.append("Category: " + context.at(0) + "\n");
        str.append("File: " + context.at(1) + "\n");
        str.append("Function: " + context.at(2) + "\n");
        str.append("Line: " + context.at(3) + "\n");
        str.append("Version: " + context.at(4));
        str.append("\n*** Information Complete ***\n");
        write(str);
        break;

        case QtWarningMsg:
        if(!(context.at(2).contains("setGeometry")))
        {
            str.append("\n*** Warning ***\n");
...
            str.append("\n*** Warning Complete ***\n");
            write(str);
            errorMsg = true;
            emit Logger::ptr->SaveSession();
        }
        break;

        case QtCriticalMsg:
        str.append("\n*** Critical ***\n");
...
        str.append("\n*** Critical Complete ***\n");
        write(str);
        errorMsg = true;
        emit Logger::ptr->SaveSession();
        break;

        case QtFatalMsg:
        str.append("\n*** Fatal ***\n");
...
        str.append("\n*** Fatal Complete ***\n");
        write(str);
        errorMsg = false;
        emit Logger::ptr->FatalSaveSession();
        QApplication::exit(-2);
    }
    Logger::mutex->unlock();
}

void Logger::write(QString str)
{
    if(!stream)
        return;

    if(str.isEmpty())
        return;

    (*stream) << str; //!!!!!!!!!!!!CRASHES HERE***********
        stream->flush();
    }

void Logger::moveLogToSession(QString sessionName)
{
    QMutex *myMutex = get_obj()->mutex;
    myMutex->lock();

    QTextStream *myStream = get_obj()->stream;
    myStream->flush();
    QFile *myLogFile = get_obj()->logFile;
    myLogFile->flush();
    myLogFile->close();
    delete myStream;

    QString path = SystemVariables::getAppData() + "/Smovault/Logs";
    if(!myLogFile->open(QFile::ReadOnly | QFile::Text))
    {
        QString errtitle = "FATAL ERROR!";
        QString errtxt = myLogFile->errorString() + "\nCould not open the log file: ";
        errtxt.append(path + "/Session.log");
        errtxt.append(".\nApplication Abort!");
        QMessageBox *mb = new QMessageBox(QMessageBox::Critical, errtitle, errtxt);
        mb->exec();
        delete mb;
        QApplication::exit(-1);
    }
    QTextStream in(myLogFile);
    QString data = in.readAll();
    myLogFile->close();
    myLogFile->remove();
    delete myLogFile;

    path = SystemVariables::getAppData() + "/Smovault/Sessions/" + sessionName;
    myLogFile = new QFile(path + "/Session.log");
    if(!myLogFile->open(QFile::WriteOnly | QFile::Text))
    {
        QString errtitle = "FATAL ERROR!";
        QString errtxt = myLogFile->errorString() + "\nCould not write to the log file: ";
        errtxt.append(path + "/Session.log");
        errtxt.append(".\nApplication Abort!");
        QMessageBox *mb = new QMessageBox(QMessageBox::Critical, errtitle, errtxt);
        mb->exec();
        delete mb;
        QApplication::exit(-1);
    }
    QTextStream out(myLogFile);
    out << data;
    out.flush();
    myLogFile->flush();

    myStream = new QTextStream(myLogFile);
    myStream->setRealNumberNotation(QTextStream::SmartNotation);
    myStream->setRealNumberPrecision(15);

    myMutex->unlock();
}

如果有人可以通过指出我的错误来帮助我,我真的很感激。

1 个答案:

答案 0 :(得分:2)

如果在调用moveLogToSession后发生崩溃,我想这是因为你破坏了流

QTextStream *myStream = get_obj()->stream;
myStream->flush();
...
delete myStream; // here

永远不会设置新流

myStream = new QTextStream(myLogFile);

get_obj()->stream = myStream; // you need THIS