10

最近、QtプロジェクトをLinuxからVistaに移行しましたが、今は盲目的にシグナルをデバッグしています。

Linuxでは、デバッグビルドでQObject :: connect()が失敗すると、stderrに警告メッセージが表示されます。Windowsでは、GUIアプリケーションのコンソール出力はなく、OutputDebugString呼び出しのみがあります。

すでにDebugViewをインストールしましたが、それは自分のqDebug()出力をうまくキャッチしますが、失敗したシグナルに対する警告はありません。

考えられる解決策の1つは、シグナルに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アプリケーションにコンソールを追加できます。
プロジェクトのプロパティに移動し、[リンカー]->[設定]で[サブシステム]を[コンソール]に変更します

ここでコードを再コンパイルすると、アプリケーションをアクティブ化したときにコンソールが表示されます。それを取り除きたい場合は、サブシステムをもう一度「Windows」に変更してください。

これがQtCreatorで行われる可能性があるかどうかはわかりません。

もう1つのオプションはAttachConsole()、コンソールを手動で作成してstdoutとstderrに接続するなどのネイティブwin32呼び出しを使用することです。詳細については、こちらをご覧ください。

于 2009-09-28T11:27:41.263 に答える
1

公式の Qt IDE: QtCreator を使用できます。これには、信号に関する問題が表示される出力コンソールが含まれています。シグナルエラーは、デバッグおよびリリース実行で出力されます。

于 2009-09-28T12:47:02.383 に答える
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 に答える