在singleton析构函数中的QTextStream上的Segfault(静态对象,__ tcf_0)

时间:2014-08-06 17:19:56

标签: qt c++11 static segmentation-fault destructor

我很难搞清楚造成这种段错误的原因。 根据{{​​3}},它与我的代码中的某些静态变量相关(请参阅下面的堆栈跟踪中的 __ tcf_0 )。 事实是,我的代码中只有一个静态变量,它是单例类的实例(见下文)。

这段代码对我来说似乎是正确的,但是当程序终止时,~Logger()(行qDebug() << "Segfault";)会抛出一个段错误。当我尝试以delete QTextStream*为例时,会发生同样的事情。但是,使用标准cout打印到控制台可以很好地工作,也可以使用标准库执行任何其他操作。似乎它只影响一些Qt类

编辑:似乎问题来自QTextStream类。的确,qDebug()使用它。其他不使用它的课程不会导致段错误。

以下是文件和堆栈跟踪:

的main.cpp

#include <QCoreApplication>
#include "Logger.h"

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    Logger::getInstance(); // Create Logger instance

    return a.exec();
}

Singleton.h

#ifndef SINGLETON_H
#define SINGLETON_H

template <class T>
class Singleton
{
protected:
    Singleton() = default;
    ~Singleton() = default;


public:
    static T &getInstance()
    {
        static T instance; // <----- static variable here
        return instance;
    }
};

#endif // SINGLETON_H

Logger.h

#ifndef LOGGER_H
#define LOGGER_H

#include "Singleton.h"

class Logger : public Singleton<Logger>
{
    friend class Singleton<Logger>;

private:
    Logger();
    ~Logger();
};

#endif // LOGGER_H

Logger.cpp

#include "Logger.h"

#include <QDebug>
#include <iostream>

Logger::Logger() : Singleton<Logger>()
{
}

Logger::~Logger()
{
    std::cout << "It works" << std::endl;
    qDebug() << "Segfault"; // <----- segfault here
}

堆栈跟踪

0   msvcrt!_msize   C:\Windows\syswow64\msvcrt.dll      0x75cff4fc  
1   ??          0x20d0ea8   
2   msvcrt!.dllonexit   C:\Windows\syswow64\msvcrt.dll      0x75cff52c  
3   (anonymous namespace)::Q_QGS_globalInstance::Holder::~Holder        47  0x6b971717  
4   ??          0xd8fc7add  
5   mingw_onexit    C:\Qt\Qt5.3.0\5.3\mingw482_32\bin\Qt5Cored.dll      0x6b9ae548  
6   atexit  C:\Qt\Qt5.3.0\5.3\mingw482_32\bin\Qt5Cored.dll      0x6b9ae5af  
7   (anonymous namespace)::Q_QGS_globalInstance::innerFunction      47  0x6b971779  
8   QGlobalStatic<QCoreGlobalData, (* (anonymous namespace)::Q_QGS_globalInstance::innerFunction), (* & (anonymous namespace)::Q_QGS_globalInstance::guard)>::operator()(void)      128 0x6b971917  
9   QCoreGlobalData::instance       63  0x6b9718f2  
10  QTextCodec::codecForLocale      680 0x6b97c475  
11  QTextStreamPrivate::reset       399 0x6b8ba6be  
12  QTextStreamPrivate::QTextStreamPrivate      330 0x6b8ba3ce  
13  QTextStream::QTextStream        954 0x6b8bb69b  
14  QDebug::Stream::Stream      66  0x6ba17d27  
15  QDebug::QDebug      78  0x6ba17dfa  
16  QMessageLogger::debug       359 0x6b78cd0e  
17  Logger::~Logger Logger.cpp  13  0x401700    
18  __tcf_0 Singleton.h 15  0x40168c    
19  msvcrt!isspace  C:\Windows\syswow64\msvcrt.dll      0x75cfc3e9  
20  msvcrt!_cexit   C:\Windows\syswow64\msvcrt.dll      0x75d037df  
21  ??              

1 个答案:

答案 0 :(得分:2)

原因很简单,QApplication在单身破坏之前被销毁,而qDebug需要QApplication对象来获取当前的文本编解码器。

这是为什么单身人士有问题的完美例子。

更改代码的方式是在QApplication对象之前清除单例,或使其成为永恒(这可能无法完全解决问题,其他某些对象可能会在QApplication被销毁后使用您的单例)。< / p>