実行時エラーが発生するとどうなりますか?


17

プログラムに実行時エラーがあるとどうなりますか?プログラムの実行は停止しますか?Arduinoにエラーの内容を教えてもらう方法はありますか?

回答:


21

まず、何が間違っているかの例をいくつか見てみましょう。

初期化されていないローカル変数

void setup() {
  int status;
  pinMode(13, OUTPUT);
  digitalWrite(13, status);
} 

コメントでエドガーボネットが指摘したようstatusに、上記のコードのようなローカル変数は、C ++コンパイラによって暗黙的に初期化されません。したがって、上記のコードの結果は不確定です。これを回避するには、必ずローカル変数に値を割り当ててください。

グローバル変数と静的変数では状況が少し異なります。

グローバル変数と静的変数は、C標準によって0に初期化されることが保証されています。

出典: AVR Libcリファレンスマニュアル-よくある質問-すべての変数を初期化すべきではありませんか?

つまり、コード内でそれらを0に初期化することについて心配する必要はありません。実際、初期化はメモリを浪費する可能性があるため、実際には回避する必要があります。0以外の値にのみ初期化します。

メモリオーバーフロー

int array[10];
int v = array[100];
array[-100] = 10;

ここでの最初の問題は、vに何が割り当てられるのかわからないことですが、さらに悪いことに、-100の位置-100への割り当てがめちゃくちゃになることもわかりませんarray

違法な指示にジャンプする

void doSomething( void ) { 
    for (int i = 0; i < 1000; i++); 
}

void setup () 
{
    void (*funcPtr)( void );

    funcPtr = &doSomething;
    funcPtr(); // calls doSomething();

    funcPtr = NULL;
    funcPtr(); // undefined behavior
}

の最初の呼び出しfuncPtr()は、実際にはの呼び出しになりdoSomething()ます。2番目の呼び出しは、未定義の動作につながる可能性があります。

起こるかもしれない他の悪いこと

たとえば、RAMが不足する可能性があります。ほかに何か。いずれにせよ、あなたのプログラムはおそらくあなたが意図した方法ではなく、実行し続けると思います。

保護の種類

コンピューターシステムでは、これらのような問題は通常、さまざまなレベルで対処されます。

  1. コンパイラーによって
  2. プログラミング言語ランタイム(Javaなど)。
  3. オペレーティングシステムまたはプロセッサによって(メモリがプログラムに予約されているアドレススペースの境界外の位置にアクセスする場合、OSまたはプロセッサはそれを防ぐための安全機構を備えている場合があります)

Arduinosにはコンパイラの保護が限られているだけで、おそらく他には何もありません。幸いなことに、マルチタスクではないため、影響を受けるプログラムはあなただけです。いずれにせよ、これらのバグのいずれかが不安定な動作につながります。

回答

前提は、上記のすべての問題がランタイムの問題であることです。

プログラムに実行時エラーがあるとどうなりますか?

プログラムは続行され、何が起こるかはランタイムエラーの副作用に依存します。null関数ポインターを呼び出すと、おそらくプログラムが不明な場所にジャンプします。

プログラムの実行は停止しますか?

いいえ、それは異常なことは何もなかったかのように進み続け、おそらくあなたが意図していないことをします。リセットされるか、不規則に動作する場合があります。一部の入力を出力に変換し、センサーを1つまたは2つ焼く可能性があります(ただし、これはほとんどありません)。

Arduinoにエラーを教えてもらう方法はありますか?

そうは思いません。先ほど言ったように、保護メカニズムはありません。言語からのランタイムサポート、OS、境界外のメモリアクセスに対するハードウェアチェックはありません(ブートローダーもカウントされません)。プログラムに注意するだけで、おそらく独自のセーフティネットを設定する必要があります。

保護されていない理由は、おそらくArduinoコントローラーが低すぎてメモリが少なすぎて、あまり重要なものを実行してはならないためです(はい、AVRによって、通常使用されるMCUを使用しないための免責事項があるようです)生命維持システムのArduino)。


1
すごい!これまでのところ、Arduino.SEで見た最高の答えです!
帽子の男

1
ありがとう!! できる限り素晴らしい答えを出すよう努力するべきだと思います。しかし、私のような答えを見て、重大な間違いを見つけることができるほど多くの本物の専門家がいないという事実を少し心配しています。実際、AVR MCUについてはあまり知りませんが、それが答えを投稿した理由です。誰かに修正してもらうかどうかを確認するためです。私のような賢いペントが正しくないことを言って、それを避けて欲しくないのは確かです。しかし、それはおそらくメタサイトの議論です。
リカルド

5
@Ricardo-1つのコメントは、明示的に初期化されていない変数は必ずしも初期化されていないということです。関数の外部で定義された変数には、一般に「自動ストレージ期間」と呼ばれるものがあり、デフォルトでゼロに初期化されます。詳細については、en.cppreference.com / w / cpp / language / default_initializationを参照してください。初期化の振る舞いは非常に複雑であるため、おそらく依存するのは危険ですが、ブランケットステートメントを作成することはおそらく素晴らしい考えではありません。
コナーウルフ14

1
あなたが作ることができるようにまた、SRAMは、リセットまたは起動時に0に初期化され、いくつかのあなたが危険な住みたい場合は、初期化されていない変数についての情報を推測します。この動作に依存するべきではありませんが、興味深いです。
コナーウルフ14

1
SRAMを使い果たしたときに何が起こるかという興味深い例があります:electronics.stackexchange.com/questions/42049/…。基本的に、スタックの一部はヒープの一部を覆い、またはその逆です。これにより、スタックフレームの一部の破損(関数の戻り値の破損など)や、無効なデータの変数への書き込みなど、興味深いことができます。
コナーウルフ14

9

実行時例外はありません。未定義の動作のみがあります。

本当に、何の例外はありませんすべてでは。無効な操作を実行しようとすると、結果は不明になります。

実装するもの除いて、ランタイムチェックはまったくありません。プログラムはベアメタルハードウェアで実行されています。ATmegaにはリングがないため、常にリング0で実行するのと同等のデスクトップです。


6

MCUを不安定な状態から取得できるメカニズムが1つあり、それはウォッチドッグタイマーです。ループで繰り返し実行されるコードを実装している場合、それは一定の時間よりも長くは実行されない場合、この時間をウォッチドッグ期間として設定し、タイマーを有効にすることができます。

次に、ループ内のタイマーを繰り返しリセットする必要があります。終了しない条件ループでコードがフリーズすると、ウォッチドッグはゼロにカウントされ、最終的にMCUをリセットします。

この方法ではデータが失われますが、AVR WDTを割り込みモードで実行する場合、MCUをリセットする前にデータを保存できます。

そのため、ウォッチドッグタイマーは、意図しない無限ループからコードを保護できます。

ドキュメント:AVR132:拡張ウォッチドッグタイマーの使用


5

このようなことを行うには、ハードウェアデバッガが必要です。しかし、通常、プログラムは期待どおりに動作しないため、問題を特定するためにコードのそのセクションを確認する必要があります。

これを行うための一般的/迅速/簡単な方法は、変数またはその他の値を出力するprintステートメントを追加して、プログラムが問題なくそのポイントに到達することを確認することです。これにより、問題をさらに特定できます。

VisualMicroにはいくつかのデバッグ機能が組み込まれていると思います


3

私は、AVR CPUにエラー検出または回復ツールがないことを前提としています。停止するか、エラーと結果を無視し続けることがあります。sachleenが言ったように、動作中にデータを出力するデバッグステートメントをプログラムに追加して、動作しているかどうかをテストする必要があります。エミュラーを使用してブレークポイントを設定すると、簡単に問題を見つけることができます。


-2

Arduinoが再起動します(つまり、再起動setup()してloop())。


1
必ずしも。実行時エラーにより、プログラムは再起動せずにループに入る可能性があります。
ニックギャモン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.