再帰処理を検出する

Understand

はじめに

再帰処理を使った関数は、実行に時間がかかることがあります。また、そのコーディング方法から無限ループなどのバグが発生しやすいため、どこに再帰処理を使用しているかを把握しておくことが重要です。今回は、Understand GUI(デスクトップアプリケーション)またはUnderstand APIを使用したPython, Perlスクリプトを使用して再帰処理をおこなっている関数の確認方法について記載します。

再帰処理とは

再帰処理とは、簡単にいうと関数内で同じ関数を呼び出すことを言います。関数内で直接呼ばれない場合でも結果的に同じ関数に戻る場合も再帰処理となります。ツリー状になっているデータを走査する場合などによく利用されるコーディング手法の一つです。

実施環境

本記事では、Windows 11、Understand 7.0 build 1220の環境にて実施しています。

Understand GUI上での確認方法

Understand GUI上で再帰処理を見つけることができます。その方法について記載します。

グラフィカルビュー

直接的な再帰処理
Understand 7.0から、直接の再帰処理について、Callsグラフに表現されるようになりました。下の画像のfuncAは関数内でfuncAを呼び出しています。そのため、funcAノードの上部に自身へ向かう矢印が表示されています。この矢印が直接の再帰を表しています。

間接的な再帰処理
Callsグラフを見ると、funcBから出る矢印がfuncC、funcDを経てfuncBに戻ってきているのが分かります。このような部分を確認することで、間接的な再帰処理を見つけることができます。

情報ブラウザー

情報ブラウザー上でも再帰状態を確認することができます。CallsまたはCalledBy情報をドリルダウンしていくと対象の関数と同じ関数が出現します。その際は「recursive」と表示されます。

Understand APIを使用した確認方法

上記のGUIの方法では各関数のCallsグラフや情報ブラウザーを確認する必要があるため、すべての再帰処理を把握したい場合には向いていません。そこで、Understand APIを使用したスクリプトにて一括して出力する方法を記載します。関数を起点に、そのCalls情報をたどり、同じ関数が呼び出されるかどうかを判定することで、再帰関数を見つけることができます。

※提供するスクリプトはテクニカルサポートの対象外となります。技術的なご質問や修正に関してはお受けいたしかねます。
※スクリプトを実行するには「Understand フローティング with API」ライセンスが必要です。

サンプルスクリプト(Perl)

UnderstandにはPerlで作成されたサンプルスクリプト(acjf_recursion.pl)が同梱されています。こちらはプロジェクトにあるすべての再帰関数を標準出力に表示します。

C:\Program Files\SciTools\plugins\Scripts\Perl\acjf_recursion.pl

実行方法

Understandに同梱されているPerl「uperl.exe」を使用して実行します。

uperl acjf_recursion.pl -db myProject.und

オプション
以下のオプションが設定されています。

オプション名指定条件説明
-db必須Understandプロジェクトフォルダー(.und)を指定します。
-def任意定義元情報を出力します。
-help任意ヘルプ情報を表示します。

実行結果

標準出力に再帰関数名の一覧が表示されます。

サンプルスクリプト(Python)

現状、Understandには該当するPythonスクリプトの提供はありません。そこで弊社にて作成してみました。
ここで紹介する弊社作成のスクリプト(findRecursiveFunc.py)はこちらからダウンロード可能です。是非お試しください。

実行方法

funcRecursiveFunc.pyをUnderstandに同梱されているPython「upython.exe」を使用して実行します。

オプション

今回作成したfindRecursiveFunc.pyには、以下のオプションが設定されています。

オプション名指定条件説明
-db必須Understandプロジェクトフォルダー(.und)を指定します。
-func任意検索対象の関数名を指定します。

プロジェクトすべてを検索する場合
-dbオプションにUnderstandプロジェクトフォルダーを指定して実行します。

upython findRecursiveFunc.py -db myProject.und

特定の関数が再帰処理かどうかを検索する場合

-funcオプションに対象の関数名を指定して実行します。

upython findRecursiveFunc.py -func myfunc -db myProject.und

実行結果

今回作成したスクリプトでは、CSVに出力するようにしました。

実行中の出力

結果CSV

関数名,ファイル
funcA,C:\Work\C\recursive\sample.c
funcB,C:\Work\C\recursive\sample.c
funcC,C:\Work\C\recursive\sample.c
funcD,C:\Work\C\recursive\sample.c

間接的な再帰(funcB→funcC→funcD)がある場合は、そのすべてを出力します。

まとめ

GUIでの検索は、検索対象が定まっている場合や影響分析の一環で再帰処理を見つけることに利用できる一方、作成したスクリプトでは一括して再帰処理を洗い出す際に有効です。業務によって使い分けて活用することができると思います。また、Pythonスクリプトは簡易的なサンプルとして作成しています。一度お試しいただき、自身にあったカスタマイズを試してみてはいかがでしょうか。