ページ 1 / 1
二次元配列の動的確保
Posted: 2017年6月10日(土) 21:21
by makaraito
コード:
#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
Re: 二次元配列の動的確保
Posted: 2017年6月10日(土) 21:38
by Math
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]
Re: 二次元配列の動的確保
Posted: 2017年6月10日(土) 21:44
by makaraito
検証ありがとうございます!私が試したのは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;
}
Re: 二次元配列の動的確保
Posted: 2017年6月10日(土) 21:50
by みけCAT
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している (未定義動作)
Re: 二次元配列の動的確保
Posted: 2017年6月10日(土) 21:59
by makaraito
お二人ともありがとうございました!!
コード:
ptr = (int **)calloc(H,sizeof(int));
↑を
コード:
ptr = (int **)calloc(H,sizeof(int*));
としたら上手くいきました!(callocの戻り値は省略...)
よくよく考えるとダブルポインタに入るのはポインタですね(-_-;)