• ベストアンサー

配列の不正アクセスについて

C++初心者です。 配列の不正アクセスの例外処理について教えてください。 void func(int* a){   try{     a[5]=1;   }catch(...){     printf("error!");   } } void main(){   int a[5];   func(a); } 上記のような配列の不正アクセスに対し、 例外を発生させたいのですが、 現状、例外は発生せず動作してしまいます。 例外を発生させ、安全に動作するようにするには どうしたらいいのでしょうか? すいませんが、お願いします。

質問者が選んだベストアンサー

  • ベストアンサー
  • jacta
  • ベストアンサー率26% (845/3158)
回答No.1

普通の配列では例外は発生しません。 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>をインクルードする必要があります。

fcknsho
質問者

お礼

素早い回答ありがとうございます。 標準ライブラリを使うのですね! 早速、修正します。 ありがとうございます。

その他の回答 (2)

  • jacta
  • ベストアンサー率26% (845/3158)
回答No.3

おかしな回答があるので再度回答します。 > 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]) {   /* 省略 */ } としてもよいでしょう。

fcknsho
質問者

お礼

訂正ありがとうございます。 初心者のため配列の取り扱いには 悩まされているので、 こういった情報は本当にためになります。 ありがとうございました。

回答No.2

言語仕様上、 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; }

fcknsho
質問者

お礼

回答ありがとうございます。 assertの場合だとプログラムが中断するため、 私の理想の動作と少し違います。 中断せず、例外として処理することで、 内部的に不正アクセスを対処したかったので… 説明不足で申し訳ありません。 しかし、記述方法はとても参考になりました。 ありがとうごうざいました。

関連するQ&A