高見知英の技術ログ

技術関係のログをQiitaから移行してきました。プログラミングのほか、使っているアプリの細かい仕様についてなど書いていきます。

Lazarusアプリ終了時にメモリリークチェック用ダイアログが表示される件

このブログはLazarus(FreePascal)アドベントカレンダー21日目の記事です。

qiita.com

今回のテーマはLazarusのアプリを終了すると表示されることがある デバッグレポートについて。

f:id:TakamiChie:20211214164602p:plain
Heap dump heaphtc unitのダイアログ

プロジェクトオプションの「コンパイラオプション\デバッグ\Heaptrcユニットを使用する」をチェックした構築モードでコンパイルを行なうと、起動したアプリケーションの終了時にこのようなダイアログが表示されます。

これはオプションに記載の通り、メモリリークの監視を行なうHeaptrcというユニットの出力ダイアログで、アプリケーション内で解放し忘れたオブジェクトがあるとここに表示されます。

中にはそのメモリを取得したファイル上の行番号も記載されているので、メモリリーク解消のための手がかりにはなるかと。

ログをダイアログではなく、ログファイルに出力する

このダイアログ、出力が多い場合は複数回に分けて表示され、いつまで経ってもダイアログが表示され続けるというちょっと厄介な性質を持っています。

ダイアログが煩わしい場合は、heaptrc.setHeapTraceOutputというメソッドでファイル名を指定することで、ログの出力先をファイルに変更することができます。

{$IFOPT D+}
  setHeapTraceOutput('trace.log');
{$ENDIF}

とはいえログの出力が終わるまでアプリケーションの実行が続くという性質は変わりありませんので、それでもログの出力が長すぎていつまで経ってもデバッグ実行が止まらない・・・ という場合は、Lazarusの実行メニューやツールバーから「終了」してしまいましょう。

自分個人で使っている場合にこれが出られると困る という場合は?

作ったアプリケーションのメインユーザーが自分自身で、自分自身が使うときはデバッグモードのバイナリを使っている という方も少なくないのではないかと思います。

ただそんなときにもこのトレースの出力が出続ける となるとさすがに煩わしいですね・・・。

そんなときは、構築モードを分けて以下のような構築の仕方にするのが良いのかなと思います。

  • リリースする場合:Releaseモード
  • Lazarusデバッガ上で実行する場合:Debugモード
  • 自分個人で使う場合:Defaultモード

そんなときに便利なものとして、構築モードがあります(いままでの記事でも何度か話題にしているので今更ですが…)

デバッグおよびリリースモードを作成

プロジェクトオプションより、コンパイラオプションノードを選択、上部の構築モードの右側にある「…」のボタンをクリックします。

f:id:TakamiChie:20211214170845p:plain
構築モードを編集する

Lazarusにはよくある構築モード構成として、「デバッグおよびリリースモードを作成」という機能がありますので、これを使います。

f:id:TakamiChie:20211214171011p:plain
デバッグおよびリリースモードを作成

すると、Defaultモードの下に、DebugとReleaseという構築モードが追加されるので、OKをクリックします。

f:id:TakamiChie:20211214171127p:plain
構築モードが追加された

ここでダイアログを閉じるとアクティブな構築モードがDebugになるので、IDE上でアプリケーションを実行するときはDebug、自分用にビルドするときはDefaultを選ぶようにします。

毎回手動でモードを切り替えるのは面倒くさい!

とはいえ毎回手動でモードを切り替えるのは面倒くさいですよね。その場合はツールメニューの外部ツールより、Defaultビルドを行なうメニューなどを作っておくと良いでしょう。

  • タイトル:Defaultでビルド(自分に分かれば何でもいい)
  • プログラムファイル名:C:\lazarus\lazbuild.exe
  • 引数:--build-mode=Default --no-write-project $ProjFile()
  • 作業ディレクトリ:$ProjPath()
  • オプション:FPCメッセージの出力をスキャン、"make"メッセージの出力をスキャンにチェック

f:id:TakamiChie:20211214172336p:plain
外部ツールの設定

これで、このメニューを選択したときだけDefaultモードでコンパイルが行なわれ、かつアクティブな構築モードは切り替わりません。

ただしこのDefaultモードでHeaptrcを使っていない場合はsetHeapTraceOutputメソッドの呼び出しがエラーになってしまいます。

なので、Defaultモードの「コンパイラオプション\カスタムオプション」の値に「-dDEFAULT」を追加しておきましょう。

f:id:TakamiChie:20211214172836p:plain
カスタムオプションの追加

次にsetHeapTraceOutputの呼び出しを次のように修正します。

{$IFOPT D+}
{$IFNDEF DEFAULT}
  setHeapTraceOutput('trace.log');
{$ENDIF}
{$ENDIF}

これでDefaultモードのときはこの行が実行されなくなります。