ページ

2013年11月10日日曜日

arm-none-eabi-gccでの静的変数コンストラクタの問題について

STM32F3DiscoveryでC++のプログラムを書いてます。
GNUのarm-none-eabi-gccを使って、bareCortexMを参考に自前で作ったプロジェクトで開発しています。

その中で、

  • std::listやstd::setを静的変数にして使うと例外が起きる。
  • sbrkで落ちてるわけでもなくメモリ確保はうまくいっているし、そもそも静的変数にしなければ問題が起きない。
  • 静的コンストラクタイディオム(staticの初期化を利用してクラスのインスタンス化前に初期化コードを動かすあれです)がうまく機能しない。
みたいな問題に悩まされてました。

どうやら原因は静的変数の初期化を行うコードがないことが原因のようです。
STM32に付属しているスタートアップスクリプトを利用している場合は、__libc_init_arrayがmain関数へ処理を移す前に呼ばれていて、この中で静的コンストラクタを呼び出す処理がなされているようです。

ところが、bareCortexMにはこれにあたるコードが存在しませんでした…

独自にスタートアップスクリプトを書いていたり、-nostdlibする場合には自力で.init_arrayを参照して静的コンストラクタを呼んであげる必要があります。

こちらに参考コードがありました。

extern void (**__init_array_start)();
extern void (**__init_array_end)();

inline void static_init()
{
  for (void (**p)() = __init_array_start; p < __init_array_end; ++p)
    (*p)();
}
--
[追記]
結局、PeripheralLibaryに付属しているスタートアップファイルとリンカスクリプトを使うことで落ち着きました。
標準のスタートアップスクリプトには__libc_init_arrayを呼ぶコードがあるので、問題なく静的変数の初期化が行われます。

ですが、静的変数の呼び出し順序に関してC++の罠にはまってしまいました…
これに関しては別のエントリにまとめました。

0 件のコメント:

コメントを投稿