これは当方が実際に遭遇したことだが、任意のクラスポインターをenumのキーを使って格納している配列で、一部環境で動作させた時に原因不明のEXC_BAD_ACCESSが発生してクラッシュするという問題に直面した。思った以上に厄介な問題で、根本的な解消にはならず、また別の問題を引き起こしかねないものの、最低限クラッシュしないで済むようにした。今回は私が使った方法を簡単に説明したい。
例としては、以下のような配列を使った時である。
[code lang=”cpp”]// barは別で定義しているものとする
class bar;
enum baz {
BAZ_ALPHA = 0,
BAZ_BETA,
BAZ_GAMMA,
BAZ_MAX,
};
bar *bar_arr[BAZ_MAX];[/code]
これを使った際に、ある環境では問題なく動くのに、ある環境ではそれを参照して利用しようとした時にEXC_BAD_ACCESSが発生してクラッシュするということがあったのだ。
正直なところ、この問題について自分なりに原因を探ってみたが、よくわからないといった状況であったため、やむなく別手段をとることにした。それが以下である。
[code lang=”cpp”]// barは別で定義しているものとする
class bar;
enum baz {
BAZ_ALPHA = 0,
BAZ_BETA,
BAZ_GAMMA,
BAZ_MAX,
};
std::map<baz, bar> bar_map;[/code]
こうすることによって、対症療法的ではあるが、クラッシュが発生しなくなったのである。
これは、単純にenumの最大値分のサイズを格納したポインター配列からbazで定義されているキーをベースとした連想配列に置き換えただけである。
特殊な使い方をしていなければこれに置き換える際はそれほど修正は必要というわけではなく(場合によっては型を変えるだけで済んでしまう)、ほぼ流用は可能だが、使い方によっては今までのやり方ができなくなる可能性もある。また、処理が複雑になることでパフォーマンスの低下も避けられない可能性がある ((C++11以降ではunordered_mapを使うという方法もあるが、こちらは多少パフォーマンスが改善されるがキーの順番が保証されなくなる)) 。
個人的にはenumをキーとした通常配列で使っていたものを連想配列に置き換えるのはパフォーマンス上必ずしも望ましいとは言えないと考えているが、特定の環境でクラッシュが発生しているといった時の対症療法として使ってみるという手段としてはありなのじゃないか?と考えている。
ウェブマスター。本ブログでITを中心にいろいろな情報や意見などを提供しています。主にスマートフォン向けアプリやウェブアプリの開発を携わっています。ご用の方はコメントかコンタクトフォームにて。