動的配列への情報転送時のアクセス違反

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
K_K

動的配列への情報転送時のアクセス違反

#1

投稿記事 by K_K » 15年前

初投稿です。よろしくお願いします。

コード:

void GetSPRData(unsigned char*** spr_data, int *num_chip){

	unsigned char char_data[**] = { ww,   //枚数
                       xx1,    //size_x1枚目
                       yy1,    //size_y1枚目
                       zz1,zz1,・・・//deta1枚目、size_x*sizyバイトのデータ
                       xx2,
                       yy2,
                       zz2,zz2,・・・以降降3枚目のサイズ情報とデータ、4枚目の・・・と続く };
	int i = 0;
	int k;
	int l;
	int num;
	unsigned char size_x;
	unsigned char size_y;
	
	*num_chip = (int)char_data[0];
	*spr_data = new unsigned char*[*num_chip];

	i = 0;	
	while(i<*num_chip){
		if(i == 0)
			num = 1;
		else
			num += 2+char_data[num]*char_data[num+1];

		size_x = char_data[num];
		size_y = char_data[num+1];
		*spr_data[i] = new unsigned char[2+size_x*size_y];
		for(k = num, l =0; k<num+size_x*size_y+2; k++, l++){
			*spr_data[i][l] = char_data[k];
		}
		i++;
	}
};
//~~~~
unsigned char** spr_charcter1;
int num_chip_character1;
	GetSPRData(&spr_charcter1, &num_chip_character1);
このような関数を作ってポインタに枚数とデータ分の動的配列を割り当て後
用意したキャラクタデータをその配列へ転送するようにしたいのですが
>*spr_data[l] = char_data[k];
の部分で2巡目(l=1以降)から0xC0000005のアクセス違反が発生します。
(~.exe の 0x00451a70 でハンドルされていない例外が発生しました: 0xC0000005:
場所 0xcdcdcdcd に書き込み中にアクセス違反が発生しました。)
割り当て自体はうまくいっているようなので、動的配列の指示の仕方に問題があると思うのですが
エラーの原因が分かる方いましたらどうぞご指摘ください。
環境はWinXPSP3, コンパイラはVC++2010Expressです。
理解度は、Cについては文法に一通り目を通して試した程度で、C++は各概念について理解した程度です。

アバター
h2so5
副管理人
記事: 2212
登録日時: 15年前
住所: 東京
連絡を取る:

Re: 動的配列への情報転送時のアクセス違反

#2

投稿記事 by h2so5 » 15年前

何がしたいのかよく分からないのですが、
コードを見る限り、char_data の内容は固定なんですよね?

だったら最初からchar_data の内容を spr_charcter1に転送するデータの形式と同じにして、
そのままchar_data の内容を spr_charcter1にコピーすればいいのではないですか?

あと、なぜ int *num_chip を引数に取っているのかも分かりません。
外部から (int)char_data[0];の値を参照したければ、返り値で済むと思います。

アバター
bitter_fox
記事: 607
登録日時: 15年前
住所: 大阪府

Re: 動的配列への情報転送時のアクセス違反

#3

投稿記事 by bitter_fox » 15年前

K_K さんが書きました:

コード:


        *spr_data[i] = new unsigned char[2+size_x*size_y];
        for(k = num, l =0; k<num+size_x*size_y+2; k++, l++){
            *spr_data[i][l] = char_data[k];
        }
>*spr_data[l] = char_data[k];
の部分で2巡目(l=1以降)から0xC0000005のアクセス違反が発生します。
(~.exe の 0x00451a70 でハンドルされていない例外が発生しました: 0xC0000005:
場所 0xcdcdcdcd に書き込み中にアクセス違反が発生しました。)

恐らく演算子の優先順位の問題だと思います。
C言語では演算子の優先順位を次のようにしています。

BohYoh さんが書きました:

コード:

優先順位	演算子	形式	名称	結合性
1
[]	x[y]	添字演算子	左

2
*	*x	単項*演算子(間接演算子)	右
http://www.bohyoh.com/CandCPP/C/operator.html - 引用元(一部省略)

これに基づいて展開すると、

コード:

        *spr_data[i] = new unsigned char[2+size_x*size_y];

コード:

        *(*(spr_data+i)) = ...;
となり、

コード:

        for(k = num, l =0; k<num+size_x*size_y+2; k++, l++){
            *spr_data[i][l] = char_data[k];
        }

コード:

        for (...){
                *(*(*(spr_data+i)+l) = ...;
        }
となってしまいます。

これは
*(spr_data)と
*(spr_data[l])と同義になります。
これだと
spr_dataの値をアドレスとしてその実体に代入することになり。
下も同様にspr_data[l]の値をアドレスとしてその実体に代入してしまっています。

次のようにしてみてください。

コード:

(*spr_data)[i] = ...;
(*spr_data)[i][l] = ...;

K_K

Re: 動的配列への情報転送時のアクセス違反

#4

投稿記事 by K_K » 15年前

>bitter_foxさん
ご指摘の通り修正したところ、無事データを読み込むことができました。ありがとうございます。
ポインタと演算子の優先順位の問題は、ポインタのインクリメントがよく取り上げられますが
こういうケースもあるとは思いつきませんでした。
今後、アドレス渡しなどでポインタを利用するときはよく気をつけて、予防のために()をつけるようにしようと思います。
本当にありがとうございました。

>h2so5さん
補足すると、この関数と配列は動作試験用に作成しているもので、char_data自体の形式はかえられませんでした。
最終的には、この関数で独自形式の外部ファイルをオープンして読み取れるように作り変える予定です
(char_dataのデータ順序はその外部ファイルのものです)。
ゲーム開始時にこの関数を利用して、引数として渡したポインタアドレスで動的配列を用意して
ゲームキャラ1体に必要な画像用データを纏めたファイルから、データを丸ごと読み込もうと考えています。
なので、char_deta配列の要素を返り値として参照できる形にはできません。
int *num_chip を引数に取っているのも画像用データの枚数を記憶しておくためです。

今回、同関数内での動的配列利用時のアクセス違反の原因について教えていただきたかったため
コード部分で自分がやりたい事と聞きたい事が書いてある以上、上のような経緯の説明は不要と思い記載しませんでした。
情報が小出しになってしまいすみませんでした。

閉鎖

“C言語何でも質問掲示板” へ戻る