実機でのメモリ アクセス中にシステムがダウンする原因とは?
以下のようなメモリ アクセスを実機で行った場合、ARM の仕様上エラーが発生し、 ARM 自身の処理が停止します。
uint16 n[2];
uint16* p;
// 奇数番地のアドレス位置に移動し、
// アラインをまたぐデータの転送を行います。
p = (uint16*)((char*)n + 1);
*p = 0;
このコードでは、uint16 型の配列で連続したメモリ空間を確保し、 char 型分だけアドレス位置をずらしています。 そのアドレス位置から uint16 型のデータを転送しようとするとアラインをまたいでしまうため、 ARM の仕様上エラーが発生します。
その他にも、以下のような場合にシステムがダウンします。
- MALLOC 関数で取得したポインタに NULL チェックをせずにアクセスした場合など、 NULL ポインタへアクセスした場合。
- 配列に対して範囲外のインデックスを指定してアクセスした場合など、 無効なアドレスへアクセスした場合。
端末のメモリの全容量と空き容量を知るには?
端末に搭載されているメモリ容量を取得するには、 ISELL_GetDeviceInfo() を使用します。
また、現在使用されているメモリ容量取得するには、 IHEAP_GetMemStas() を使用します。
この 2 つの値を引き算することで、空き容量を知ることができます。
【 コード例 】
続きを読む »
BREW にガベージコレクションを行うAPIはありますか?
BREW にはガベージコレクションを行うAPIはありません
ヒープに空きがあるのに MALLOC() でメモリ確保に失敗します!?
IHEAP_CheckAvail() を使って、本当にヒープからメモリが確保できるのか調べてください。
一般に、
ヒープ内の合計空きメモリサイズ ≠ MALLOC() で確保できるメモリサイズ
です。
ヒープ上でメモリの確保と解放が繰り返されると 、空きのメモリブロックが飛び飛びになります。
MALLOC() はヒープの連続した空きのメモリブロックからメモリを確保する関数です。
構造体をゼロで初期化するには?
構造体をゼロで初期化するには ZEROAT 関数を使用してもよいですが、C 言語で次のように書く方が簡単です。
AEEDeviceInfo devinfo = {0};
ZEROAT 関数を使用する場合は、以下のように記述します。
AEEDeviceInfo devinfo;
// 構造体をゼロで初期化する。
ZEROAT(&devinfo);
メモリの扱いに関する注意点は?
BREW プログラミングでは、メモリの確保と解放はプログラマが明示的に行なわなければなりません。
Java のようにガベージコレクションが働いて、使われなくなったメモリが自動的に再利用されることはありません。
確保したメモリを解放し忘れると、使用可能なメモリ容量が次第に減少する、いわゆる「メモリリーク」という現象が発生します。
「メモリリーク」は検出が困難なバグのひとつでとても厄介です。
「メモリリーク」の問題を避けるには、確保したメモリは必ず解放する必要があります。
また、メモリの確保と解放を何度も繰り返していると、空きのメモリ領域が断片化し、時間の経過と共にまとまったメモリ領域を確保することが次第に困難になります。
このような事態を避けるには、滅多に必要とされないものを除いて、アプリの開始時またはレジューム時にアプリ全体が必要とするメモリをまとめて確保し、アプリの終了時またはサスペンド時にそのメモリをまとめて解放するようなプログラミングスタイルが必要です。