二次元配列の動的確保

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

二次元配列の動的確保

#1

投稿記事 by makaraito » 8年前

コード:

#include <stdio.h>
#include <stdlib.h>

int main(void){
	int row = 4;
	int col = 7;
	int** arr;
	int i, j;
	// 領域の確保
	arr = (int**)calloc(row, sizeof(int));
	for (i=0; i<row; i++) {
		arr[i] = (int*)calloc(col, sizeof(int));
	}
	// アクセス
	for(i=0; i<row; i++){
		for(j=0; j<col; j++){
			arr[i][j] = i + j;
		}
	}
	for(i=0; i<row; i++){
		for(j=0; j<col; j++){
			printf("%d\t", arr[i][j]);
		}
		putchar('\n');
	}	
	// 解放
	for (i=0; i<row; i++) {
		free(arr[i]);
	}
	free(arr);
	return 0;
}

Runtime error(Exit status:139(Invalid memory reference))
このエラーがでますorz
おかしいところを教えてくださいorz

Math

Re: 二次元配列の動的確保

#2

投稿記事 by Math » 8年前

Windows10、VS2017Communityではエラーにならないけど?(^^;

コード:

1>------ すべてのリビルド開始: プロジェクト:ConsoleApplication6, 構成: Debug Win32 ------
1>c1.c
1>ConsoleApplication6.vcxproj -> D:\z17\c\ConsoleApplication6\Debug\ConsoleApplication6.exe
1>ConsoleApplication6.vcxproj -> D:\z17\c\ConsoleApplication6\Debug\ConsoleApplication6.pdb (Partial PDB)
========== すべてリビルド: 1 正常終了、0 失敗、0 スキップ ==========

コード:

0       1       2       3       4       5       6
1       2       3       4       5       6       7
2       3       4       5       6       7       8
3       4       5       6       7       8       9
続行するには何かキーを押してください . . .
[/size]

makaraito

Re: 二次元配列の動的確保

#3

投稿記事 by makaraito » 8年前

検証ありがとうございます!私が試したのはpaiza.i/oってサイトです。
もしよろしければ、下のコードとはどう違うのかご教授お願いしますorz

コード:

#include <stdio.h>
#include <stdlib.h>
int main(void){
    int i,j;
    int H,W;
    H = 5;
    W = 6;
    int **ptr;
    ptr = (int **)calloc(W,sizeof(int));
    
    for(i=0;i<H;i++){
        ptr[i] = (int *)calloc(H,sizeof(int));
    }
    
    for(i=0;i<H;i++){
        for(j=0;j<W;j++){
            ptr[i][j] = i + j;
        }
    }
    
    for(i=0;i<H;i++){
        for(j=0;j<W;j++){
            printf("%d\t",ptr[i][j]);
        }
        printf("\n");
    }
    free(ptr);
    free(ptr);
    return 0;
}

アバター
みけCAT
記事: 6734
登録日時: 14年前
住所: 千葉県
連絡を取る:

Re: 二次元配列の動的確保

#4

投稿記事 by みけCAT » 8年前

makaraito さんが書きました:もしよろしければ、下のコードとはどう違うのかご教授お願いしますorz
No: 1のコードは環境によっては上手く動くでしょうが、No: 3のコードは確実に未定義動作になります。

No: 1のコードの問題点
  • callocの戻り値をチェックしていない (失敗して返ってきたNULLをデリファレンスすると未定義動作)
  • 10行目で1要素のサイズをsizeof(int*)ではなくsizeof(int)にしている (LP64など、intのサイズがint*のサイズより小さい環境では範囲外アクセス→未定義動作の原因)
No: 3のコードの問題点
  • callocの戻り値をチェックしていない (失敗して返ってきたNULLをデリファレンスすると未定義動作)
  • 9行目で1要素のサイズをsizeof(int*)ではなくsizeof(int)にしている (LP64など、intのサイズがint*のサイズより小さい環境では範囲外アクセス→未定義動作の原因)
  • ptrはW(=6)要素確保したのに、11行目、15行目、21行目ではH(=5)回ループしている (確保した数より少ないので、不自然だが問題は無い)
  • ptrはH(=5)要素しか確保していないのに、16行目、22行目ではW(=6)回ループしている (範囲外を読み書きするので未定義動作)
  • 28行目で、freeしたポインタをもう一度freeしている (未定義動作)
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

makaraito

Re: 二次元配列の動的確保

#5

投稿記事 by makaraito » 8年前

お二人ともありがとうございました!!

コード:

    ptr = (int **)calloc(H,sizeof(int));
↑を

コード:

    ptr = (int **)calloc(H,sizeof(int*));
としたら上手くいきました!(callocの戻り値は省略...)

よくよく考えるとダブルポインタに入るのはポインタですね(-_-;)

返信

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