dポイントプレゼントキャンペーン実施中!

C++初心者です。

配列の不正アクセスの例外処理について教えてください。

void func(int* a){
  try{
    a[5]=1;
  }catch(...){
    printf("error!");
  }
}

void main(){
  int a[5];

  func(a);
}

上記のような配列の不正アクセスに対し、
例外を発生させたいのですが、
現状、例外は発生せず動作してしまいます。

例外を発生させ、安全に動作するようにするには
どうしたらいいのでしょうか?

すいませんが、お願いします。

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>をインクルードする必要があります。
    • good
    • 1
この回答へのお礼

素早い回答ありがとうございます。

標準ライブラリを使うのですね!
早速、修正します。

ありがとうございます。

お礼日時:2012/01/27 11:19

おかしな回答があるので再度回答します。



> 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])
{
  /* 省略 */
}

としてもよいでしょう。
    • good
    • 0
この回答へのお礼

訂正ありがとうございます。

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

ありがとうございました。

お礼日時:2012/01/27 11:34

言語仕様上、



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;
}
    • good
    • 0
この回答へのお礼

回答ありがとうございます。

assertの場合だとプログラムが中断するため、
私の理想の動作と少し違います。

中断せず、例外として処理することで、
内部的に不正アクセスを対処したかったので…
説明不足で申し訳ありません。

しかし、記述方法はとても参考になりました。
ありがとうごうざいました。

お礼日時:2012/01/27 11:30

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!