【问题标题】:Segfault on QTextStream in singleton destructor (static object, __tcf_0)单例析构函数中 QTextStream 上的段错误(静态对象,__tcf_0)
【发布时间】:2014-09-29 17:49:01
【问题描述】:

我很难弄清楚是什么导致了这个段错误。 根据my research,它与我的代码中的一些静态变量有关(请参阅下面的堆栈跟踪中的 __tcf_0)。 事实上,我的代码中只有一个静态变量,它是单例类的实例(见下文)。

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

编辑:看来问题出在QTextStream 类。事实上,qDebug() 使用它。其他不使用它的类不会导致段错误。

这是文件和堆栈跟踪:

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

【问题讨论】:

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


    【解决方案1】:

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

    这是单例存在问题的完美例子。

    更改代码以在QApplication 对象之前清除单例,或使其永久化(这可能无法完全解决问题,因为在QApplication 被销毁后其他对象可能会使用您的单例)。

    【讨论】:

    • 是的,我正要发布答案。我还在犹豫为什么QTextCodec::codecForLocale() 会返回NULL,但你证实了我的假设。谢谢你。确实,您是对的,单身人士是邪恶的……我花了几个小时才弄清楚这一点。我已经吸取了教训。
    猜你喜欢
    • 2012-04-15
    • 1970-01-01
    • 2012-12-26
    • 1970-01-01
    • 2014-03-23
    • 2015-12-27
    • 2015-08-06
    • 1970-01-01
    • 2011-05-20
    相关资源
    最近更新 更多