プログラミング

【組み込みC言語】スタック使用量見積もり/調査

以前、スタックオーバーフローについて説明し、スタックオーバーフローが発生したときの調査の大変さについて書きました。

しかし、通常はスタックオーバーフローが発生してから調査をするのではなく、あらかじめスタック量を見積もり調査をしたうえで、スタック量に余裕ができるようにサイズを決めるものです。

ということで、今回はスタック量の見積もり方法・調査方法についてまとめます。

スタック量の見積もり方法

まず最初に、スタック量の見積もり方法について紹介します。

といっても、通常はコンパイラやRTOSなどにスタック見積もりツールが付属しているので、それを使用するだけです。
各タスクの一番上の関数で使用されるスタック使用量を確認すれば、一発でタスクでのスタック使用量を見積もることができます。

この見積もりツールでどこまで正確に把握できるのかはわかりませんが、経験上そこまで大きな誤差はないと思います。

ただし、1点大きな注意点があって、

関数ポインタを使用している場合はその先のスタック量が見積もれない

という点です。

通常の関数コールだけであればどの関数が呼ばれるか確定しているのでスタックの見積もりはできますが、関数ポインタの場合、その先にどの関数が呼ばれるかが確定していないので、ツールではそこまで見ることができないということですね。

この場合、上位から関数ポインタまでのスタック量と、関数ポインタで呼ばれる関数のうち最もスタック量が多い関数のスタック量を手動で足し合わせるという操作が必要になります。

関数ポインタの数が増えれば増えるほど組み合わせが増えるので、調査が大変になっていきますね・・・

スタック量の調査方法

スタック量の調査をする場合、実際にプログラムを走らせてみてどこまでスタックが使用されたかを確認することになります。

やり方としては、大きく分けで以下の2つの方法があります。

  • デバッグで直接RAMにあるスタック領域の値を確認しにいく
  • スタック領域を精査するプログラムを実装し、通信などで出力する

どちらもやるべきことの原理は同じで、手法が異なるだけです。

上記の調査の前に共通して実施しなければいけないことは、

  • 調査するタスクのパスをすべて通過すること

です。

上記の手法でわかることは、あくまで現時点で使用しているスタック量なので、最もスタックを使用するパスを通らなければ最大スタック量を調査することはできません。ですので、すべてのパスを通ることが重要になります。
関数が深いところが必然的にスタック量も多くなりますが、そう言ったところはパスを通すのが難しかったり忘れがちだったりするので、注意が必要です。

毎回同じ操作をするのも大変ですしミスも生じやすいので、自動化できていると良いですね。

それでは、手法について詳しく見ていきましょう。

デバッグでの調査方法

調査の手順は以下の通りです。

  • スタックが使用される前にbreakを張ってプログラムを止め、対象のスタック領域をすべてFFにする
  • 対象のタスクの全パスを通す操作をする
  • breakでプログラムを停止し、FFに変えた領域のうち、どこまで値が変更されているかを確認する

初期状態をFFにしておき、その後に値が変更された領域はスタックとして使用された領域、ということです。
どこまで値が変更されているかを確認することによって、スタックの使用量を確認できることがわかります。

ところで、最初にbreakを張る、スタックが使用される前に、というのはどこのことを指すのでしょうか?

これは、main関数が呼ばれる直前が良いです。main関数が呼ばれてしまうと、RTOSによってスタックを使用し始めてしまうので、その後にFFに変更すると入れたはずのデータがpopできなくなって暴走する可能性があります。

main関数が呼ばれる場所はboot領域のアセンブラで書かれている場所なので、アセンブラの部分にbreakを張ることになります。

なお、初期状態はFFではなく00でもOKですが、00はスタック中によく保存される値でもあるので、FFの方がおすすめです。

調査プログラム実装による調査方法

調査プログラムを実装する場合も基本は同じです。スタック領域の一番最初のアドレスから順にさかのぼって値を確認し、00(またはFF)以外の値は初めて現れるまで検索してサイズを計算するだけです。

こちらを使うメリットは以下の通りです。

  • プログラムを止めることなく確認できる(デバッグでなくてもOK)
  • 内部で自動演算するので、結果だけをすぐに確認できる

しかし、デメリットも存在します。

デバッグの場合は起動時にFFの値を書き込みましたが、この方法で実施するときは明確に00またはFFに初期化されない可能性があります。このとき、RAMの値が不定値になる可能性があるので、正確な値を出せない可能性があります。

とはいえ、経験上では00になっていることが多いと思いますので、そこまで気にする必要はないかもしれません。ダメになる可能性があると分かりつつこちらの方法を使用していただければよいかと思います。

ただ、この方法を使うためには、外部に情報を出す必要がありますので、何かしらの外部通信がないと難しいです。

メンテナンス用の通信が専用にあるのが最もやりやすいので、最初からそういったハードウェア設計にしてもらえるのがベストですが、それが無理だとしてもほかの通信と兼用で値が出せるようにしたいところです。

まとめ

以上、スタック量の見積もり/調査方法についてまとめました。

C言語の組み込みでは、必ずスタック量の確認をする必要が出てきます。2つの手法を書きましたが、両方のやり方をしっかり理解して、実装できるならば実装を、できない理由があるのならばデバッグで確認していただければよいかと思います。

スタックの状況をしっかり把握して余計なトラブルを起こさないように気を付けていきましょう!

COMMENT

メールアドレスが公開されることはありません。

CAPTCHA