10

我最近将我的 Qt 项目从 Linux 迁移到了 Vista,现在我正在盲目地调试信号。

在 Linux 上,如果 QObject::connect() 在调试构建中失败,我会在 stderr 上收到警告消息。在 Windows 上,GUI 应用程序没有控制台输出,只有一个 OutputDebugString 调用。

我已经安装了DebugView,它很好地捕获了我自己的 qDebug() 输出,但仍然没有对失败信号发出警告。

一种可能的解决方案是使用 QtCreator 的信号自动完成功能,但我喜欢 Eclipse,两者都使用是 PITA。关于如何在运行时获取信号/插槽信息的任何想法?

编辑:我刚刚意识到 connect() 返回 bool,它解决了当前的问题,尽管它可能很丑陋。但是,这并不能解决QMetaObject::connectSlotsByName()失败的情况,并且这种情况会自动与小部件一起运行。

4

7 回答 7

10

调用静态函数 QErrorMessage::qtHandler()。

根据文档,这“使用 qInstallMsgHandler() 安装消息处理程序并创建显示 qDebug()、qWarning() 和 qFatal() 消息的 QErrorMessage”。

或者,使用 qInstallMsgHandler() 安装消息处理程序。

另一种选择(在 qt-interest 帖子中描述)是这样的:

#ifdef _DEBUG
#define connect( connectStmt ) Q_ASSERT( connect( connectStmt ) ) 
#endif

...对于它的价值,这里有一些我编译的信号和插槽调试建议:http: //samdutton.wordpress.com/2008/10/03/debugging-signals-and-slots-in-qt/

于 2009-09-28T12:41:19.570 回答
4

我喜欢的解决方案是设置

QT_FATAL_WARNINGS=1

调试时在程序的环境中。这会使程序崩溃,给你一个很好的回溯,特别是如果你在调试器中运行代码。如果您不希望崩溃,请参阅上面的答案。

于 2009-09-28T15:30:45.203 回答
2

我的方法是重新绑定 Qt 日志引擎,qInstallMsgHandler并将我自己的日志记录到文件和控制台。

这样,我知道所有的错误/警告消息都被记录下来,即使在程序停止执行后我也可以分析它们。

PS:QtCreator 会截获这些消息并在应用程序输出窗格中显示它们。

于 2009-09-28T12:15:17.557 回答
1

如果您使用 Visual Studio,您可以将控制台添加到任何 QT 应用程序。
转到项目属性,在链接器->设置下将“子系统”更改为“控制台”

现在重新编译您的代码,您将在激活应用程序时出现控制台。如果你想摆脱它,只需将 SubSystem 再次更改为“Windows”

我不确定这是否可能与 QtCreator 有关。

另一种选择是使用本机 win32 调用,例如AttachConsole()手动创建控制台并将其附加到 stdout 和 stderr。有关详细信息,请参见此处。

于 2009-09-28T11:27:41.263 回答
1

您可以使用官方的 Qt IDE:QtCreator。它包含一个输出控制台,您可以在其中看到任何信号问题。在调试和发布运行中输出信号错误。

于 2009-09-28T12:47:02.383 回答
1

大多数时候我只想偶尔注意一下:只需在“int dummyPutBreakpointHere=23;”行上放一个断点

in main.C:

static QtMessageHandler defaultMessageHandler;
void myRazorsharpMessageHandler(QtMsgType type, const QMessageLogContext& context, const QString& msg) 
{
    if ( type > QtDebugMsg ) {
        int dummyPutBreakpointHere= 23;
    }
    defaultMessageHandler(type, context, msg);
}
...
later in main(): defaultMessageHandler= qInstallMessageHandler(0);
于 2014-11-20T18:43:53.380 回答
0

您可以很容易地重定向 stdout/stderr:创建一个派生自 std::basic_streambuf 并重载 xsputn() 和 overflow() 的类,然后使用例如 std::cerr.rdbuf( instanceOfYourRedirectClass ) 将所有 stderr 输出重定向到回调函数你供应。

这是我使用的简化版本;根据您的需要,您可能需要添加额外的逻辑来处理行尾字符等的处理。

template< class Elem = char, class Tr = std::char_traits<Elem> >
class Redirector : public std::basic_streambuf<Elem, Tr>
{
  typedef void (*pfncb) ( const Elem*, std::streamsize );

public:
  Redirector( std::ostream& a_Stream, pfncb a_Cb ) :
    m_Stream( a_Stream ),
    m_pCbFunc( a_Cb ),
  {
      //redirect stream
    m_pBuf = m_Stream.rdbuf( this );
  };

  ~Redirector()
  {
      //restore stream
    m_Stream.rdbuf( m_pBuf );
  }

  std::streamsize xsputn( const Elem* _Ptr, std::streamsize _Count )
  {
    m_pCbFunc( _Ptr, _Count );
    return _Count;
  }

  typename Tr::int_type overflow( typename Tr::int_type v )
  {
    Elem ch = Tr::to_char_type( v );
    m_pCbFunc( &ch, 1 );
    return Tr::not_eof( v );
  }

 protected:
  std::basic_ostream<Elem, Tr>& m_Stream;
  std::streambuf*               m_pBuf;
  pfncb                         m_pCbFunc;
};

用法:

  void outcallback( const char *ptr, std::streamsize count )
  {
    if( *ptr != gc_cEOL )  //ignore eof
      OutputDebugString( ptr );
  }

  Redirector<> redirect( std::cout, mycallback );
于 2009-09-28T11:53:03.470 回答