打印信号/插槽的跟踪称为

Posted

技术标签:

【中文标题】打印信号/插槽的跟踪称为【英文标题】:print trace of signals/slots called 【发布时间】:2016-09-20 14:48:21 【问题描述】:

有没有办法打印被调用的信号和槽?

我在 Qt 中遇到了一个奇怪的死锁,这种死锁仅在跨多个线程的特定条件下发生,我想知道调用信号/插槽的顺序。

当然,对于slots,我写的是方法体,最坏的情况下,我可以手动添加一个打印出来的方法。但是信号体是自动生成的,所以这是不可能的,除非我写一个自定义的 moc,这对于这个任务来说似乎有点过头了......

【问题讨论】:

【参考方案1】:

如果利用内置挂钩,则可以自动检测所有信号以及使用 Qt 4 connect 语法连接的所有插槽。不幸的是,QtPrivate::QSlotObject 没有实现这些钩子:使用 Qt 5 语法连接的插槽需要手动检测(例如,通过将仿函数连接到它们,或向它们添加代码)。

信号通知可用于连接信号。没有信号的对象,以及有其他连接的对象的一些信号,将不会被报告。这大概就是你想要的。

因此:

// https://github.com/KubaO/***n/tree/master/questions/signal-spy-39597233
#include <QtCore>
#include <private/qobject_p.h>

int signalToMethodIndex(const QMetaObject * mo, int signal)

    Q_ASSERT(signal >= 0);
    for (int i = 0; i < mo->methodCount(); ++i) 
        if (mo->method(i).methodType() == QMetaMethod::Signal) 
            if (signal == 0) return i;
            -- signal;
        
    
    return -1;


class Spy 
    static QThreadStorage<bool> entered;
    static void signalBegin(QObject *caller, int signalIndex, void **) 
        if (entered.localData()) return;
        QScopedValueRollback<bool> rollentered.localData(), true;
        auto index = signalToMethodIndex(caller->metaObject(), signalIndex);
        if (index >= 0)
            qDebug() << "SIGNAL" << caller << caller->metaObject()->method(index).methodSignature();
    
    static void slotBegin(QObject *caller, int index, void **) 
        if (entered.localData()) return;
        QScopedValueRollback<bool> rollentered.localData(), true;
        qDebug() << "SLOT" << caller << caller->metaObject()->method(index).methodSignature();
    
public:
   static void start() 
       QSignalSpyCallbackSet set&signalBegin, &slotBegin, nullptr, nullptr;
       qt_signal_spy_callback_set = set;
   
;
QThreadStorage<bool> Spy::entered;


struct Class : QObject 
    Q_SIGNAL void aSignal();
    Q_SLOT void aSlot()  qDebug() << "slot"; 
    Q_OBJECT
;

int main(int argc, char ** argv) 
    Spy::start();
    QCoreApplication appargc, argv;
    Class obj;
    QObject::connect(&obj, SIGNAL(aSignal()), &obj, SLOT(aSlot()));
    obj.setObjectName("obj");
    emit obj.aSignal();

#include "main.moc"

输出:

SIGNAL Class(0x7fff51901af0, name = "obj") "objectNameChanged(QString)"
SIGNAL Class(0x7fff51901af0, name = "obj") "aSignal()"
SLOT Class(0x7fff51901af0, name = "obj") "aSlot()"
slot

【讨论】:

这太棒了!你介意向 Qt 官方问题跟踪器建议这个吗?这将对所有 Qt 程序员有很大帮助。没关系,让它与 Qt 5 或 6 一起工作可能是个问题 - 让我们开始吧,看看它落在哪里。 @mrts 但这不是任何问题。这只是有人提出的问题。这不是 Qt 错误或类似的东西。至于帮助所有 Qt 程序员:他们肯定知道 *** :) 确实没有比谷歌搜索结果中出现的答案更高的可见度(感谢 SO 的 SEO)。 嗯,主要问题是它不适用于现代 Qt 信号槽连接,因此有必要进行更广泛的讨论。我认为没有人真正认真地考虑过 Qt 中的信号槽跟踪开发人员体验,SO 中有很多这样的问题,我在其他答案中偶然发现了这个宝石。话虽如此,无意推动:)!

以上是关于打印信号/插槽的跟踪称为的主要内容,如果未能解决你的问题,请参考以下文章

如何转储 goroutine 堆栈跟踪?

跟踪信号发生器如何产生宽频带信号

BOC同步跟踪BOC信号跟踪算法的MATLAB仿真

GPS信号跟踪捕获基于FPGA的GPS系统跟踪捕获算法的Verilog实现

linux strace-跟踪进程的系统调用或是信号产生情况,lstrace-跟踪己丑年调用库函数情况,进程跟踪调试命令

使用strace 工具跟踪系统调用和信号