1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Arduino IDEで例外処理(Try-Catchなど:ほとんど失敗)

Posted at

Arduino IDEで例外処理

Arduino IDEで例外処理(Try-Catchなど)を「トライ」したときの記録。ただし、期待どおり動作せず。

まずは情報から

Arduinoボード向けコンパイルオプション

”try-catch”が含まれるコードをBuildしようとすると、コンパイルオプション”-fexceptions”を使え、、というエラーメッセージが表示される。platform.txt(どこか深いところにある)にある”-fno-exceptions”を削除し、”-fexceptions”を記載することが必要。下記リンクは参考情報。

なお、ESP32ボード向け(今回はM5Stack利用)では、このコンパイルオプション追加は不要であった。

単純なコードだが

下記コードは単純なコードだが、Arduino UnoではBuildできず。どうも、tryやcatch内に”Serial.println()”があるためのようだ。

// ESP32:OK   Arduino Uno:NG

void setup() {
  Serial.begin(9600);
}

void loop() {
  try {
    Serial.println("1");
  } catch (...) {
    Serial.println("2");
  }
}

もしかしたら、これもコンパイルオプションで回避できるのかもしれない(見つからず、、ではあったが)。ただし、ESP32ボード向けでは、上記コードはBuildできる。

深堀り(調査)

調べると次のサイトに、

"Since there are no standard exception classes defined (and the ArduinoSTL library doesn't compile on the due out-of-the-box), you'll have to write your own exception classes, i.e something like this:"
という記述が見つかる。自分で例外クラスを定義する必要があるのかもしれない、、。

サンプルコード

上記サイトをほぼそのまま利用し、次のコードを作成(ESP32ボード向け)。

class Exception
{
  private:
  const char* _msg;
  public:
  Exception(const char* msg)
  {
    _msg = msg;
  }

  const char* Message() const
  {
    return _msg;
  }
};

void ThrowExceptionFunc(int n)
{
  if (n > 1) {
    throw Exception("Something bad happened");
  }
}

void ValidateExceptionHandling(int val)
{
  Serial.print("val = "); Serial.println(val);
  try
  {
    ThrowExceptionFunc(10/val);
    Serial.println("Exception was not thrown:");
  }
  catch(Exception& ex)
  {
    Serial.print("Exception happened:");
    Serial.println(ex.Message());
  }
  catch (...) {
    Serial.println("Other exceptions");
  }
}

void setup() {
  Serial.begin(115200);
}

void loop() {
  while (Serial.available()) {
    String data = Serial.readStringUntil('\n');
    int num = data.toInt();
    ValidateExceptionHandling(num);
  }
}

概要は下記のとおり。

  • PC(シリアル)から入力された数値(エラー処理は未考慮)を、例外処理関数(ValidateExceptionHandling())に渡して処理
  • その処理関数内で、入力数値(val)により、定義した例外クラスを呼び出し
    • ”10/val”の値が1以上でThrow(ThrowExceptionFunc()にて)
  • Throwを受け取る処理(catch(Exception& ex))を定義
  • すべての例外を受け取る処理(catch(...))を定義

結果

val = 2
Exception happened:Something bad happened
val = 14
Exception was not thrown:
val = 0
Guru Meditation Error: Core  1 panic'ed (IntegerDivideByZero). Exception was unhandled.
Core 1 register dump:
PC      : 0x400d0c5c  PS      : 0x00060b30  A0      : 0x800d0d3e  A1      : 0x3ffb1f60  
A2      : 0x00000000  A3      : 0x3ffbfe88  A4      : 0x3ffbfe88  A5      : 0x3ffb1f80  
A6      : 0x00000003  A7      : 0x00000000  A8      : 0x800d0c5a  A9      : 0x3ffb1f40  
A10     : 0x0000000a  A11     : 0x00000001  A12     : 0x0000000a  A13     : 0x3ffb84ac  
A14     : 0x00ff0000  A15     : 0x3ffb1e70  SAR     : 0x0000000a  EXCCAUSE: 0x00000006  
EXCVADDR: 0x00000000  LBEG    : 0x400014fd  LEND    : 0x4000150d  LCOUNT  : 0xffffffff  

ELF file SHA256: 0000000000000000

Backtrace: 0x400d0c5c:0x3ffb1f60 0x400d0d3b:0x3ffb1f80 0x400d1f29:0x3ffb1fb0 0x400860ed:0x3ffb1fd0

Rebooting...
ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x17 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:1
load:0x3fff0018,len:4
load:0x3fff001c,len:1216
ho 0 tail 12 room 4
load:0x40078000,len:10944
load:0x40080400,len:6388
entry 0x400806b4

”val = 2”がThrowされるケース、”val = 14”がThrowされないケースとなる。”val = 0”にて、0で割るが発生し、すべての例外を受け取る処理(catch(...))が動作することを期待したが、そのとおりにならず、リセットしてしまった。

少々調べると、ESP32向けでは、”stdexcept”というファイルに、例外クラスが定義されていることがわかった。

  • logic_error
  • domain_error
  • invalid_argument
  • length_error
  • out_of_range
  • runtime_error
  • range_error
  • overflow_error
  • underflow_error

これらを、catch()に記載してもうまくいかず。また、他のロジック(アルゴリズム)により、上記に類似した例外を発生させようとしたが、うまくいかず。

終わりに

結局、期待どおりとならず。忘れた頃にリトライするかもしれない。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?