qInstallMessageHandler
カスタムログ機能を登録するために使用します。この関数は、メッセージをフォーマットし (タイム スタンプを追加するなど)、コンソールとログ ファイルに出力します。
私の懸念は、Qt ライブラリ コンポーネント ( QDateTime
、QDir
、 ... など) が、などQFile
を呼び出すことができるかどうかです。qDebug()
qWarning()
はいの場合、これは無限再帰につながる可能性があります...
簡単な答えは、メッセージ ハンドラーを再入力しないようにすることです。
// C++11, Qt 5.4+
void myMessageHandler(…) {
thread_local bool entered = false;
if (entered) return; // oops
QScopedValueRollback set{entered, true};
…
}
// C++11, Qt 4.8+
void myMessageHandler(…) {
thread_local bool entered = false;
if (entered) return; // oops
QScopedValueRollback back{entered};
entered = true;
…
}
// C++98, Qt 4
QThreadStorage<bool> entered;
void myMessageHandler(…) {
if (entered.localData()) return;
QScopedValueRollback back(entered.localData());
entered.localData() = true;
…
}
これは、後世にとって古くてばかげた答えでした:
ロギングが同期している場合にのみ、無限再帰が発生します。ロギングを非同期にするとすぐに、もう問題は発生しません。シグナルを発行した直後に終了し、キュー接続を介したシグナル発行はゼロまたはQMetaCallEvent
関連するスレッドのイベント キューにインスタンスを追加するだけです。
非同期ログは、メッセージ ハンドラーでシグナルを発行し、明示的にキューに入れられた接続を介してシグナルに接続されたスロット/ファンクターからのログ書き込みを処理することによって実現されます。おそらく、ロガーを独自のスレッドに常駐させたいと思うでしょう。そのため、これは非常に自然なアプローチであり、うまく機能します。