TOP > eMbedded Visual C++ Tips > 第4回 CEではスタックに注意

eMbedded Visual C++ Tips 第4回 CEではスタックに注意

■ CEはスタックが小さい

 随分と間が空いてしまったが今回はスタックフレーム(以下スタック)の話をしよう。x86のWin32プログラマがはまりやすいのがこのスタックの問題なのである。例えば次のようなコードがあるとしよう。

void func()
{
    char[65536];

    int i;
    for(i = 0;i < 65536;i++) {
        // 何らかの処理
    }
}
 このコードはx86のWin32では動くかもしれないが、CEではまず動かない。func()がコールされた瞬間にスタックで領域が確保できずにプログラムが落ちてしまうのだ。(Pocket PC 2002で試したところ画面が固まった。)実はこれはUNIXとか組み込み系のプログラマには当たり前の話で64KBもの巨大な?変数をローカルで書いてはいけないのだ。

 ところがx86のWin32(Visual C++ 6.0)ではコンパイル時のスタックのデフォルトが1MBであることからすんなり動いてしまう(その辺りを知った上で使うならば手軽で良いのだが)のである。x86でこのぬるま湯に浸かっていたプログラマはこの行儀の悪いコードが問題の原因であることが分からずにしばし悩むことになるだろう。

■ コードによる対処法

 このように大きなメモリ領域が必要な場合、CEでの対処法としてはmalloc等でヒープからメモリを確保するかstaticで静的に確保してしまうか、あるいはグローバル変数にするかである。

 簡単に書くなら変数の前にstaticを付けて終わりだが、当然そのメモリ領域はプロセスが生きている間は常に確保されているわけで無駄と言えば無駄である。メモリリソースの限られるCEでは動的に領域を確保するのが良いだろう。mallocを使っても良いし、APIのHeapAllocを使用しても良い。

 HeapAllocを使用する場合、ヒープのハンドルが必要なのでGetProcessHeapかHeapCreateで取得する。メモリを使い終わったらHeapFreeで領域を解放するのを忘れてはいけない。独自のヒープをHeapCreateで生成した場合は最後にHeapDestroyで破棄するのも忘れずに。

    HANDLE hHeap;

    hHeap = GetProcessHeap(); // プロセスヒープのハンドル取得
    buf = (char*)HeapAlloc(hHeap,0,65536); // メモリの割り当て

    // 確保したメモリを使用して何らかの処理

    HeapFree(hHeap,0,buf); // メモリ解放

■ リンクオプションによる対処法

 また、別な解決方法としてはリンクオプションでスタックフレームのサイズを変更する方法がある。以下はeMbedded Visual C++ 3.0の例である。

stack

 標準で/stack:0x10000すなわち64KBになっている部分を任意に変更して問題を解決することが可能だ。設定を変更したら確実にビルドし直そう。さもなければ設定が実行ファイルに反映されない。

(2004/07/12)


Copyright(C) 2004 モバイル開発系(K) All rights reserved.

[Home]