- ベストアンサー
配列の不正アクセスについて
C++初心者です。 配列の不正アクセスの例外処理について教えてください。 void func(int* a){ try{ a[5]=1; }catch(...){ printf("error!"); } } void main(){ int a[5]; func(a); } 上記のような配列の不正アクセスに対し、 例外を発生させたいのですが、 現状、例外は発生せず動作してしまいます。 例外を発生させ、安全に動作するようにするには どうしたらいいのでしょうか? すいませんが、お願いします。
- みんなの回答 (3)
- 専門家の回答
質問者が選んだベストアンサー
普通の配列では例外は発生しません。 arrayのatメンバ関数を使えば同様のことが実現できるはずです。 #include <array> #include <stdio.h> void func(std::array<int, 5>& a){ try{ a.at(5)=1; }catch(...){ printf("error!"); } } int main(){ std::array<int, 5> a; func(a); } > 安全に動作するようにするには mainの返却値をintにしないと未定義の動作になります。 また、printfを使うのであれば、<stdio.h>をインクルードする必要があります。
その他の回答 (2)
- jacta
- ベストアンサー率26% (845/3158)
おかしな回答があるので再度回答します。 > void func(int a[5]) ↑のように書いても、aは配列型ではなくポインタ型になります。 したがって、sizeof(a)/sizeof(a[0])と書いても、要素数は取得できず、でたらめな結果しか得られません。 単純な配列で要素数も関数に渡したいのであれば、別の引数として渡すか、次のようにテンプレートを使います。 template <std::size_t N> void func(int (&a)[N]) { /* 省略 */ } あるいは、サイズが必ず5なのであれば、 void func(int (&a)[5]) { /* 省略 */ } としてもよいでしょう。
お礼
訂正ありがとうございます。 初心者のため配列の取り扱いには 悩まされているので、 こういった情報は本当にためになります。 ありがとうございました。
- chie65536(@chie65535)
- ベストアンサー率44% (8740/19838)
言語仕様上、 func(int* a) で受けたaは「ポインタ」であり、このポインタは「int配列のどこを指しているか判らない」ので、範囲チェックは出来ません。 例えば、呼び出し元で func(&a[2]); として呼び出すと、func関数内での有効な添え字の範囲は「-2から2」になります。 いつも有効範囲が「0~4」だとは限らないのです。 なので、配列の添え字は、基本「範囲チェックもされないし、範囲外をアクセスした場合は動作が未定義」なのです。 以下のように、引数をポインタにせず、配列の要素数が明示された配列の参照渡しを行い、関数内で「要素数が何個あるのか判るように書いて」から、assertマクロで「範囲外チェックを行う」のが良いでしょう。 #include <assert.h> void func(int a[5]) { assert(5 < sizeof(a)/sizeof(a[0])); /*範囲外なら異常終了*/ assert(5 >= 0); /*範囲外なら異常終了*/ a[5] = 1; } int main(void) { int a[5]; func(a); return 0; }
お礼
回答ありがとうございます。 assertの場合だとプログラムが中断するため、 私の理想の動作と少し違います。 中断せず、例外として処理することで、 内部的に不正アクセスを対処したかったので… 説明不足で申し訳ありません。 しかし、記述方法はとても参考になりました。 ありがとうごうざいました。
お礼
素早い回答ありがとうございます。 標準ライブラリを使うのですね! 早速、修正します。 ありがとうございます。