【问题标题】:How to know which QObject::connect is failing如何知道哪个 QObject::connect 失败
【发布时间】:2018-03-16 11:43:13
【问题描述】:

我有一个具有数十个信号槽连接的应用程序,特别是多个类(具有分解)正在实现几乎相同的QObject::connect 信号槽,我面临的问题有时是,在 QtCreator 应用程序输出 em>,我得到了通常的错误:

QObject::connect: 无法连接 (null)::SessionClosed() 到 mainWindow_Desktop::stop_Scanning()

但它没有任何迹象表明错误来自哪个文件/行或代码段,其代价是我必须检查所有类似的连接以检测哪个出错了! 我的问题是:我有什么方法可以直接知道错误所指的文件/行

【问题讨论】:

  • 对每个未标记为Qt::UniqueConnection 的连接使用断言。 assert(connect(...))
  • 你可以安装一个event filter on qWarning 并调用一个断言/抛出异常或任何你喜欢的,来处理所有类似的情况。
  • @DmitrySazonov,问题更糟,我可能描述得不够充分,错误来自从未实例化的类..由于它们的多态结构,它们在运行时没有对象
  • @Jaa-c assert 在发布模式下构建后将变为无操作(请参阅NDEBUG 宏)。在这种情况下调试愉快:)
  • @Ruslan:用于测试目的的内部发布版本通常有断言......而对于生产代码,你将它们关闭......

标签: qt qt-creator signals-slots qobject


【解决方案1】:

QMetaObject::Connection QObject::connect() 有一个返回值,它带有一个隐式 bool 转换运算符,因此您可以使用 if 语句简单地测试它是否成功,并在必要时发出警告,如果出现详细警告,则可以告诉您发生在哪里已启用。

您当然可以自己手动使用__FILE____LINE____FUNCTION__ 宏。

【讨论】:

  • 谢谢。如果我没看错的话,这种方法没有任何限制.. 仅作为调试工具.. 我不认为投入生产是不切实际的。
  • 是的,它纯粹是一个运行时的东西,你可以根据返回值采用不同的代码路径,实现错误检查、修复、缓解、终止、任意数据输出和自然设置断点,否则不会到达。
【解决方案2】:

QMessageLogger::warningQMessageLogger::critical 等处设置断点。然后,您的应用程序将在来自 Qt 的qWarningqCritical 等消息上停止,调用堆栈会告诉您它们的来源。

示例代码:

#include <QObject>

void f()
{
    QObject::connect(0,"kkk",0,"aaa");
}

int main()
{
    f();
}

编译后,当我用 GDB 运行它时,我得到:

$ gdb -ex 'set breakpoint pending on' -ex 'b QMessageLogger::warning' \
      -ex r -ex bt ./test
Reading symbols from ./test...done.
Function "QMessageLogger::warning" not defined.
Breakpoint 1 (QMessageLogger::warning) pending.
Starting program: /tmp/test/test 
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Breakpoint 1, QMessageLogger::warning (this=this@entry=0x7fffffffd2e0, msg=msg@entry=0x7ffff7c3ac80 "QObject::connect: Cannot connect %s::%s to %s::%s") at global/qlogging.cpp:541
541     {
#0  QMessageLogger::warning (this=this@entry=0x7fffffffd2e0, msg=msg@entry=0x7ffff7c3ac80 "QObject::connect: Cannot connect %s::%s to %s::%s") at global/qlogging.cpp:541
#1  0x00007ffff7b64a4d in QObject::connect (sender=0x0, signal=0x400838 "kkk", receiver=<optimized out>, method=<optimized out>, type=<optimized out>) at kernel/qobject.cpp:2618
#2  0x0000000000400788 in f () at test.cpp:5
#3  0x00000000004007a0 in main () at test.cpp:10

在这里我们可以看到对connect 的错误调用发生在test.cpp:5 中的f()

【讨论】:

  • 我正在尝试。谢谢。
  • 听起来它最终会捕获几乎所有警告源,而不是隔离连接问题。更不用说需要更慢和更大的调试版本了。
  • @dtech 你说的慢是什么意思?您可以根据需要进行优化,但包括调试信息以便能够找到调用connect 的点。由于 Qt 函数几乎从不内联,因此优化不应该是一个复杂的问题。
  • 我的意思是调试构建非常庞大,构建时间更长,启动时间更长,执行速度也更慢。因此,如果您只想知道连接是否失败,那么绝对不是可选方案。调试版本用于...调试:)
猜你喜欢
  • 2021-06-10
  • 1970-01-01
  • 2015-06-18
  • 2020-12-09
  • 1970-01-01
  • 2023-01-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多