LoginSignup
21
21

More than 5 years have passed since last update.

静的解析に引っかからなかったメモリ破壊の話

Last updated at Posted at 2013-11-28

業務で出会ったバグの話です。

現象

  • どういう訳かグローバルなカウンタ変数がリセットされる
  • メモリブレイクを仕掛けても、リセットされる瞬間が引っかからない

解析結果

typede.h
#define true   1u
#define false  0u
hogehoge.c
/* グローバル変数 */
unsigned char g_is_error_flg;
mogemoge.c
extern unsigned int g_is_error_flg;

void func1( void )
{
    g_is_error_flg = false;
    return;
}
choco.c
/* グローバル変数 */
unsigned char g_loop_counter;

void func2( void )
{
    if( priority ) {
        g_loop_counter++;
    }
}

リセットされるカウンタは g_loop_counter です。
いったい何がいけないのか、わかりますか?
mapファイルで確認すると、g_loop_counterg_is_error_flg の次のアドレスでした。

ステップ実行して g_is_error_flg = false;g_loop_counter0 が書き込まれるのを確認できました。
ただ、g_is_error_flg = false; の何がいけないのか、しばらくは分かりませんでした。

mogemoge.c から見ると、g_is_error_flg の宣言はどっか別の所にあって、mogemoge.c 内では unsigned int として扱うしかない訳です。
ところが、アドレスの割り付けとしてはg_is_error_flgg_loop_counter で1バイトずつでしか割り当てられていない訳で。

困った事に、他のいくつかのファイルでも g_is_error_flg は使われていたんですが、mogemoge.c 以外のファイルでは正しく extern 宣言されていたんですよねー。

今は、他に同様のケースがないかどうか、どうやって確認しようかをプロジェクト内で相談中です。
grepによる力技は避けたいよなあ、と誰もが口に出して言ってます。
どなたか、いい知恵ありませんか?

IARっていう統合開発環境を使ってたんですが、
静的解析では引っかかりませんでした。
ただ、メモリブレイクでも引っかからなかったのは、なんか納得いかなかったですね。

教訓

extern 宣言は変数宣言のコピペで作ろう!

21
21
9

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
21
21