テキストを表示させるプログラムでのアクセス違反

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
残念
記事: 36
登録日時: 8年前

テキストを表示させるプログラムでのアクセス違反

#1

投稿記事 by 残念 » 8年前

残念と申します。
今回、テキストドキュメントに書いてある内容を表示させるものを作ろうと思いこのようなコードを書いてみたところ、
source.cpp

コード:

#include "stdio.h"
#include"Share.h"
#include"stdlib.h"
#include "DxLib.h"
int lord(char ***a);

int main(void)

{
	int m,k;
	char **a[1];
	m=lord (a);
	for (k = 0; k < m; k++){
		printf("%s\n", a[0][k]);
	}

		

		
		
		
		return 0;
	
}
int lord(char ***a){
	FILE *fp;
	char st[150];
	int j, m=0;
	fp = fopen("loadk.txt", "r");
	fscanf_s(fp, "%d", &m);
	for (j = 0; j < m; j++){
		fscanf_s(fp, "%s", st,20);
		printf("%s\n", st);
		a[j] = (char**)malloc(sizeof(char*));
		*a[j] = (char*)malloc(sizeof(char)*(strlen(st)));
		strcpy(*a[j],st);
	}
	return m;
}
loadk.txt

コード:

3
a
bb
c
実行中、
int mainでのprintf関数でa[0][0]が表示され、k=1になった時に
アクセス違反が発生しました。

どこの箇所に間違いがあるか教えてください。お願いします。

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

Re: テキストを表示させるプログラムでのアクセス違反

#2

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

  • aは1要素しか確保されていないのに、確保されていないa[1]以降にアクセスしている(34、35行目)
  • 終端文字を格納する分の領域が足りない(35行目)
  • 開いたファイルをクローズしていない(lord関数)
  • mallocで確保した領域をfreeしていない(main関数)
オフトピック
「読み込む」という意味の英単語でlordに近いものはloadだが、これは間違いではない。
例えばlord関数をこんな感じにすると、アクセス違反は無くなると思います。

コード:

int lord(char ***a){
	FILE *fp;
	char st[150];
	int j, m=0;
	fp = fopen("loadk.txt", "r");
	fscanf_s(fp, "%d", &m);
	for (j = 0; j < m; j++){
		fscanf_s(fp, "%s", st,20);
		printf("%s\n", st);
		if (j == 0) a[j] = (char**)malloc(sizeof(char*));
		(*a)[j] = (char*)malloc(sizeof(char)*(strlen(st)+1));
		strcpy((*a)[j],st);
	}
	return m;
}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ざんねん

Re: テキストを表示させるプログラムでのアクセス違反

#3

投稿記事 by ざんねん » 8年前

こんなかんじですかね?

コード:

#include "stdio.h"
#include"Share.h"
#include"stdlib.h"
#include "DxLib.h"
int load(char ***a);

int main(void)

{
	int m,k;
	char **a[1];
	m=load (a);
	for (k = 0; k < 3; k++){

		printf("%s\n", a[0][k]);
	}

		
	free(*a);
	free(**a);
		
			
		
		return 0;
	
}
int load(char ***a){
	FILE *fp;
	char st[150];
	int j, m = 0;
	fp = fopen("loadk.txt", "r");
	fscanf_s(fp, "%d", &m);
	for (j = 0; j < m; j++){
		fscanf_s(fp, "%s", st, 20);
		printf("%s\n", st);
		if (j == 0) a[j] = (char**)malloc(sizeof(char*));
		(*a)[j] = (char*)malloc(sizeof(char)*(strlen(st) + 1));
		strcpy((*a)[j], st);
	}
	fclose(fp);
	return m;
}
(free関数で開放する部分ってa,*a,**aであってますかね?)

残念
記事: 36
登録日時: 8年前

Re: テキストを表示させるプログラムでのアクセス違反

#4

投稿記事 by 残念 » 8年前

残念です。みけCATさん、有難うございました。

あと、No.3で言っていたことなのですが、free(**a);だけでよかったようです。
最後に編集したユーザー 残念 on 2015年9月09日(水) 21:02 [ 編集 1 回目 ]

box
記事: 2002
登録日時: 13年前

Re: テキストを表示させるプログラムでのアクセス違反

#5

投稿記事 by box » 8年前

解決したとのことですが、本来は
ざんねん さんが書きました:こんなかんじですかね?

コード:

	char **a[1];
要素数1の配列が登場した時点で
「これは何かがおかしいぞ」と思うべきではないのかな、と思います。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

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

Re: テキストを表示させるプログラムでのアクセス違反

#6

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

ざんねん さんが書きました:(free関数で開放する部分ってa,*a,**aであってますかね?)
違います。
a[0]、a[0][0]、a[0][1]、a[0][2] (a[0]とa[0][0]からa[0][m-1]まで)です。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

残念
記事: 36
登録日時: 8年前

Re: テキストを表示させるプログラムでのアクセス違反

#7

投稿記事 by 残念 » 8年前

残念です。
boxさん、みけCATさん、ご指摘ありがとうございます。

みけCATさんの
「a[0]とa[0][0]~a[0][m-1]」というご指摘を参考に、
(結構複雑になりましたが)このようなコードを書いてみたところ、

コード:

#include "stdio.h"
#include"Share.h"
#include"stdlib.h"
#include "DxLib.h"
void load(char ***a, char ***b, int ***c, int ***d);

int main(void)

{
	int k;
	char **a[1], **b[1];
	int **c[1], **d[1];
	load(a, b, c, d);
	printf("%s\n", a[0][0]);
	printf("%s\n", b[0][0]);
	printf("%s\n", b[0][1]);
	printf("%s\n", b[0][2]);

	free(a[0]);
	free(a[0][0]);
	free(b[0]);
	free(b[0][0]);
	free(b[0][1]);
	free(b[0][2]);
	free(c[0]);
	free(c[0][0]);
	free(c[0][1]);
	free(c[0][2]);
	free(d[0]);
	free(d[0][0]);





	return 0;

}
void load(char ***a, char ***b, int ***c, int ***d){
	FILE *fp;
	char st[1024];
	int j = 0, m = 0, k = 0, n = 0, n1 = 0, n2 = 0, n3 = 0, n0 = 0;
	int v[4] = { 0, 0, 0, 0 };
	fp = fopen("loadk.txt", "r");
	fscanf_s(fp, "%d", &m);
	for (j = 0; j < m; j++){
		fscanf_s(fp, "%d", &k);
		if (k == 0){
			fscanf_s(fp, "%s", st, 20);
			if (n == 0){
				a[n] = (char**)malloc(sizeof(char*));

			}

			(*a)[n] = (char*)malloc(sizeof(char)*(strlen(st) + 1));

			strcpy((*a)[n], st);
			int h0 = 0, h1 = 0;
			fscanf_s(fp, "%d", &h0);
			if (n3 == 0){
				d[n3] = (int**)malloc(sizeof(int*));

			}

			(*d)[n3] = (int*)malloc(sizeof(int)*(h0));
			for (h1 = 0; h1 < h0; h1++){
				fscanf_s(fp, "%d", (**d + h0));
			}

			n++;
			n3++;

		}
		else{
			fscanf_s(fp, "%s", st, 20);
			if (n1 == 0){
				b[n1] = (char**)malloc(sizeof(char*));

			}

			(*b)[n1] = (char*)malloc(sizeof(char)*(strlen(st) + 1));

			strcpy((*b)[n1], st);

			if (n2 == 0){
				c[n2] = (int**)malloc(sizeof(int*));

			}

			(*c)[n2] = (int*)malloc(sizeof(int)*(4));
			for (n0 = 0; n0 < 4; n0++){
				fscanf_s(fp, "%d", (**c + n0));
			}

			n1++;
			n2++;
		}

	}
	fclose(fp);

}
free(a[0][0]);のところでアクセス違反がおき、
freeの順序を変え、このようにしたときは、

コード:

#include "stdio.h"
#include"Share.h"
#include"stdlib.h"
#include "DxLib.h"
void load(char ***a, char ***b, int ***c, int ***d);
int tofree[4];
int main(void)

{
	int k;
	char **a[1], **b[1];
	int **c[1], **d[1];
	load(a, b, c, d);
	printf("%s\n", a[0][0]);
	printf("%s\n", b[0][0]);
	printf("%s\n", b[0][1]);
	printf("%s\n", b[0][2]);
	free(a[0]);
	free(b[0]);
	free(c[0]);
	free(d[0]);
	for (k = 0; k < tofree[0] + 1; k++){
		free(a[0][k]);
	}
	for (k = 0; k < tofree[1] + 1; k++){
		free(b[0][k]);
	}
	for (k = 0; k < tofree[2] + 1; k++){
		free(c[0][k]);
	}
	for (k = 0; k < tofree[3] + 1; k++){
		free(d[0][k]);
	}

	return 0;

}
void load(char ***a, char ***b, int ***c, int ***d){
	FILE *fp;
	char st[1024];
	int j = 0, m = 0, k = 0, n = 0, n1 = 0, n2 = 0, n3 = 0, n0 = 0;
	int v[4] = { 0, 0, 0, 0 };
	fp = fopen("loadk.txt", "r");
	fscanf_s(fp, "%d", &m);
	for (j = 0; j < m; j++){
		fscanf_s(fp, "%d", &k);
		if (k == 0){
			fscanf_s(fp, "%s", st, 20);
			if (n == 0){
				a[n] = (char**)malloc(sizeof(char*));

			}

			(*a)[n] = (char*)malloc(sizeof(char)*(strlen(st) + 1));

			strcpy((*a)[n], st);
			int h0 = 0, h1 = 0;
			fscanf_s(fp, "%d", &h0);
			if (n3 == 0){
				d[n3] = (int**)malloc(sizeof(int*));

			}

			(*d)[n3] = (int*)malloc(sizeof(int)*(h0));
			for (h1 = 0; h1 < h0; h1++){
				fscanf_s(fp, "%d", (**d + h0));
			}

			n++;
			n3++;

		}
		else{
			fscanf_s(fp, "%s", st, 20);
			if (n1 == 0){
				b[n1] = (char**)malloc(sizeof(char*));

			}

			(*b)[n1] = (char*)malloc(sizeof(char)*(strlen(st) + 1));

			strcpy((*b)[n1], st);

			if (n2 == 0){
				c[n2] = (int**)malloc(sizeof(int*));

			}

			(*c)[n2] = (int*)malloc(sizeof(int)*(4));
			for (n0 = 0; n0 < 4; n0++){
				fscanf_s(fp, "%d", (**c + n0));
			}

			n1++;
			n2++;
		}

	}
	tofree[0] = n;
	tofree[1] = n1;
	tofree[2] = n2;
	tofree[3] = n3;
	fclose(fp);

}
ブレークポイントが発生した、と表示されました。
解決策及びなぜこうなるのかがわかる方、できればですがご教授くだされば嬉しいです。

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

Re: テキストを表示させるプログラムでのアクセス違反

#8

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

a[0]をfreeした時点でa[0][0]などにはアクセスできなくなります。
どのような入力を与えればいいかの解析が難しそうだったのでテストしていないですが、

コード:

	for (k = 0; k < tofree[0] + 1; k++){
		free(a[0][k]);
	}
	for (k = 0; k < tofree[1] + 1; k++){
		free(b[0][k]);
	}
	for (k = 0; k < tofree[2] + 1; k++){
		free(c[0][k]);
	}
	for (k = 0; k < tofree[3] + 1; k++){
		free(d[0][k]);
	}
	free(a[0]);
	free(b[0]);
	free(c[0]);
	free(d[0]);
としてみてください。
また、b[0]には1要素しか確保されていない領域へのポインタが入っているのに、b[0][1]以降にアクセスしているのはまずいと思います。
a, c, dについても同様です。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ざんねん

Re: テキストを表示させるプログラムでのアクセス違反

#9

投稿記事 by ざんねん » 8年前

残念です。
b[0][1]以降へのアクセスが危険というのは、freeの際のことでしょうか?それとも、printf関数の
時でしょうか?
教えていただけるとありがたいです。

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

Re: テキストを表示させるプログラムでのアクセス違反

#10

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

ざんねん さんが書きました:b[0][1]以降へのアクセスが危険というのは、freeの際のことでしょうか?それとも、printf関数の
時でしょうか?
両方です。
ついでにmallocやstrcpyもです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ざんねん

Re: テキストを表示させるプログラムでのアクセス違反

#11

投稿記事 by ざんねん » 8年前

残念です。解決策として、http://www.flow.cs.is.nagoya-u.ac.jp/ha ... cpp5.htmlを
参考にし、このようにしてみましたが、

コード:

#include "stdio.h"
#include"Share.h"
#include"stdlib.h"
#include "DxLib.h"
void load(char **a, char **b, int **c, int **d,int g[3]);
int tofree[4];
int main(void)

{
	int g[3];
	int k;
	char **a, **b;
	int **c;
	int	**d;
	load(a, b, c, d, g);
	printf("%s\n", a[0]);
	printf("%s\n", b[0]);
	printf("%s\n", b[1]);
	for (int i = 0; i < g[1]; i++){
		delete[] a[i];
		delete[] c[i];
	}
	for (int i = 0; i < g[2]; i++){
		delete[] b[i];
		delete[] d[i];
	}
	delete[] a;
	delete[] b;
	delete[] c;
	delete[] d;
	return 0;

}
void load(char **mn, char **sn, int **gd, int **spd,int g[3]){
	FILE *fp;
	char st[1024];
	int n,i,k,n1=0,n2=0,m;
	
	fp = fopen("loadk.txt", "r");
	for (n = 0; n < 3; n++){
		fscanf_s(fp, "%d", g+n);
	}
	mn = new char*[g[1]];
	gd = new int*[g[1]];
	sn = new char*[g[2]];
	spd = new int*[g[2]];

	for (k = 0; k < g[0]; k++){
		fscanf_s(fp, "%d", &i);
		if (i == 0){
			fscanf_s(fp, "%s", st);
			mn[n1] = new char[strlen(st)+1];
			strcpy(mn[n1], st);
			fscanf_s(fp, "%d", &m);
			gd[n1] = new int[m];
			for (n = 0; n < m; n++){
				fscanf_s(fp, "%d", gd+n1+n);
			}
			n1++;
		}
		if (i == 1){
			fscanf_s(fp, "%s", st);
			sn[n2] = new char[strlen(st) + 1];
			strcpy(sn[n2], st);
			spd[n2] = new int[4];
			for (n = 0; n < 4; n++){
				fscanf_s(fp, "%d", spd + n2 + n);
			}
			n2++;
		}
	}
	

	fclose(fp);

}
**a、**b、**c、**dの初期化をしていなかったため、load(a,b,c,d,g)で引っかかりました。
初期化は、どんな風にしたらよろしいのでしょうか?

Bull
記事: 149
登録日時: 9年前

Re: テキストを表示させるプログラムでのアクセス違反

#12

投稿記事 by Bull » 8年前

最初のload関数が間違っているような気がします。

ちょっと書き直してみました。

コード:

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

int load(char ***a);

int main(void)
{
	int m, k;
	char **a;
	m = load(&a);
	for (k = 0; k < m; k++) {
		printf("%s\n", a[k]);
	}

	for (k = 0; k < m; ++k)
		free(a[k]);
	free(a);

	return 0;
}

int load(char ***a){
	FILE *fp;
	char st[150];
	int j, m = 0;
	fp = fopen("loadk.txt", "r");
	fscanf_s(fp, "%d", &m);
	*a = (char **)malloc(sizeof(char *) * m);
	for (j = 0; j < m; j++){
		fscanf_s(fp, "%s", st, 20);
		printf("%s\n", st);
		//if (j == 0) a[j] = (char**)malloc(sizeof(char*));
		(*a)[j] = (char*)malloc(sizeof(char)*(strlen(st) + 1));
		strcpy((*a)[j], st);
	}
	fclose(fp);
	return m;
}

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

Re: テキストを表示させるプログラムでのアクセス違反

#13

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

ざんねん さんが書きました: **a、**b、**c、**dの初期化をしていなかったため、load(a,b,c,d,g)で引っかかりました。
初期化は、どんな風にしたらよろしいのでしょうか?
初期化は適当に0とNULLでも入れておいて、load関数の引数を参照にするといいかもしれません。
(全くテストしていません)
(「配列」はポインタで渡されるので、参照にしなくても中身を書き換えてくれるはず)

コード:

#include "stdio.h"
#include"Share.h"
#include"stdlib.h"
#include "DxLib.h"
void load(char **&a, char **&b, int **&c, int **&d,int g[3]);
int tofree[4];
int main(void)

{
	int g[3] = {0, 0, 0};
	//int k; // unused?
	char **a = NULL, **b = NULL;
	int **c = NULL;
	int	**d = NULL;
	load(a, b, c, d, g);
	printf("%s\n", a[0]);
	printf("%s\n", b[0]);
	printf("%s\n", b[1]);
	for (int i = 0; i < g[1]; i++){
		delete[] a[i];
		delete[] c[i];
	}
	for (int i = 0; i < g[2]; i++){
		delete[] b[i];
		delete[] d[i];
	}
	delete[] a;
	delete[] b;
	delete[] c;
	delete[] d;
	return 0;

}
void load(char **&mn, char **&sn, int **&gd, int **&spd,int g[3]){
	FILE *fp;
	char st[1024];
	int n,i,k,n1=0,n2=0,m;
	
	fp = fopen("loadk.txt", "r");
	for (n = 0; n < 3; n++){
		fscanf_s(fp, "%d", g+n);
	}
	mn = new char*[g[1]];
	gd = new int*[g[1]];
	sn = new char*[g[2]];
	spd = new int*[g[2]];

	for (k = 0; k < g[0]; k++){
		fscanf_s(fp, "%d", &i);
		if (i == 0){
			fscanf_s(fp, "%s", st);
			mn[n1] = new char[strlen(st)+1];
			strcpy(mn[n1], st);
			fscanf_s(fp, "%d", &m);
			gd[n1] = new int[m];
			for (n = 0; n < m; n++){
				// Wrong type!
				//fscanf_s(fp, "%d", gd+n1+n);
				fscanf_s(fp, "%d", *(gd+n1)+n);
			}
			n1++;
		}
		if (i == 1){
			fscanf_s(fp, "%s", st);
			sn[n2] = new char[strlen(st) + 1];
			strcpy(sn[n2], st);
			spd[n2] = new int[4];
			for (n = 0; n < 4; n++){
				// Wrong type!
				//fscanf_s(fp, "%d", spd + n2 + n);
				fscanf_s(fp, "%d", *(spd + n2) + n);
			}
			n2++;
		}
	}
	

	fclose(fp);

}
オフトピック
テストしやすいように、入力データの例をいただけますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

zannnenn

Re: テキストを表示させるプログラムでのアクセス違反

#14

投稿記事 by zannnenn » 8年前

Bullさん、みけCATさん、ありがとうございます。
今Bullさんのコードを参考に、

コード:

#include "stdio.h"
#include"Share.h"
#include"stdlib.h"
#include "DxLib.h"
void load(char ***a, char ***b, int ***c, int ***d);
int tofree[4];
int main(void)

{
	int k;
	char **a, **b;
	int **c, **d;
	load(&a, &b,&c, &d);
	printf("%s\n", a[0]);
	printf("%s\n", b[0]);
	printf("%s\n", b[1]);
	printf("%s\n", b[2]);
	
	for (k = 0; k < tofree[0] ; k++){
		free(a[k]);
	}
	for (k = 0; k < tofree[1]; k++){
		free(b[k]);
	}
	for (k = 0; k < tofree[2]; k++){
		free(c[k]);
	}
	for (k = 0; k < tofree[3] ; k++){
		free(d[k]);
	}
	free(a);
	free(b);
	free(c);
	free(d);

	return 0;

}
void load(char ***a, char ***b, int ***c, int ***d){
	FILE *fp;
	char st[1024];
	int j = 0, m = 0, k = 0,n2=0,n1=0;
	fp = fopen("loadk.txt", "r");
	fscanf_s(fp, "%d", &m);
	for (j = 0; j < m; j++){
		fscanf_s(fp, "%d", &k);
		if (k == 0){
			fscanf_s(fp, "%s", st, 20);
			if (n1 == 0){
				a[n1] = (char**)malloc(sizeof(char*));

			}

			(*a)[n1] = (char*)malloc(sizeof(char)*(strlen(st) + 1));

			strcpy((*a)[n1], st);
			int h0 = 0, h1 = 0;
			fscanf_s(fp, "%d", &h0);
			if (n1 == 0){
				d[n1] = (int**)malloc(sizeof(int*));

			}

			(*d)[n1] = (int*)malloc(sizeof(int)*(h0));
			for (h1 = 0; h1 < h0; h1++){
				fscanf_s(fp, "%d", (**d + h0));
			}

			n1++;
			

		}
		else{
			fscanf_s(fp, "%s", st, 20);
			if (n2 == 0){
				b[n2] = (char**)malloc(sizeof(char*));

			}

			(*b)[n2] = (char*)malloc(sizeof(char)*(strlen(st) + 1));

			strcpy((*b)[n2], st);

			if (n2 == 0){
				c[n2] = (int**)malloc(sizeof(int*));

			}

			(*c)[n2] = (int*)malloc(sizeof(int)*(4));
			for (int n0 = 0; n0 < 4; n0++){
				fscanf_s(fp, "%d", (**c + n0));
			}

		
			n2++;
		}

	}
	tofree[0] = n1;
	tofree[1] = n2;
	tofree[2] = n2;
	tofree[3] = n1;
	fclose(fp);

}
という感じで書き、heap bufferとかいうエラーがでて来たので、原因を考え中です。

あと、入力データの例は用意するのが当たり前ですね…すみませんでした。
newを使っているほうは
loadk.txt

コード:

4 1 3                             //g[0]~g[2]までの数
0 aaa 3 1 2 3
1 ass 1 1 1 1
1 sasa 1 1 1 1 
1 asd 0 9 0 8
mallocを使うときは
loadk.txt

コード:

4                             //mの数
0 aaa 3 1 2 3
1 ass 1 1 1 1
1 sasa 1 1 1 1 
1 asd 0 9 0 8
となっております。

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

Re: テキストを表示させるプログラムでのアクセス違反

#15

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

zannnenn さんが書きました:今Bullさんのコードを参考に、
(略)
という感じで書き、heap bufferとかいうエラーがでて来たので、原因を考え中です。
No: 7のコードと同様にmallocで確保した領域の外にアクセスする、良くないコードです。
とりあえず、入力データを

コード:

2
0 aaa 3 1 2 3
1 ass 1 1 1 1
にして、

コード:

	printf("%s\n", b[1]);
	printf("%s\n", b[2]);
をコメントアウトした状態で実行するとどうなりますか?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ざんねん

Re: テキストを表示させるプログラムでのアクセス違反

#16

投稿記事 by ざんねん » 8年前

やはり、ビルドエラーは出ませんが、実行後すぐに
Debug Error!

Program: .........exe

HEAP CORRUPTION DETECTED: after Normal block(#75)at 0x0122A6E8.
CRT detected that the application wrote to memory after end of heap
buffer.

といった文がでてきます

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

Re: テキストを表示させるプログラムでのアクセス違反

#17

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

ざんねん さんが書きました:やはり、ビルドエラーは出ませんが、実行後すぐに
Debug Error!

Program: .........exe

HEAP CORRUPTION DETECTED: after Normal block(#75)at 0x0122A6E8.
CRT detected that the application wrote to memory after end of heap
buffer.

といった文がでてきます
66行目

コード:

fscanf_s(fp, "%d", (**d + h0));
で確保した領域の外にアクセスしています。
No: 15の変更に追加で、この行を

コード:

fscanf_s(fp, "%d", (**d + h1));
としてみてください。(91行目は変えてはいけません)
また、66行目と91行目は、ともにそれぞれn1>0、n2>0のときに意図しない動作になりそうです。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

ざんねん

Re: テキストを表示させるプログラムでのアクセス違反

#18

投稿記事 by ざんねん » 8年前

そこか!…一応、エラーなく動きました。
今のところ、

コード:

#include "stdio.h"
#include"Share.h"
#include"stdlib.h"
#include "DxLib.h"
void load(char ***a, char ***b, int ***c, int ***d);
int tofree[4];
int main(void)

{
	int k;
	char **a, **b;
	int **c, **d;
	load(&a, &b, &c, &d);
	printf("%s\n", a[0]);
	printf("%s\n", b[0]);


	for (k = 0; k < tofree[0]; k++){
		free(a[k]);
	}
	for (k = 0; k < tofree[1]; k++){
		free(b[k]);
	}
	for (k = 0; k < tofree[2]; k++){
		free(c[k]);
	}
	for (k = 0; k < tofree[3]; k++){
		free(d[k]);
	}
	free(a);
	free(b);
	free(c);
	free(d);

	return 0;

}
void load(char ***a, char ***b, int ***c, int ***d){
	FILE *fp;
	char st[1024];
	int j = 0, m = 0, k = 0, n2 = 0, n1 = 0;
	fp = fopen("loadk.txt", "r");
	fscanf_s(fp, "%d", &m);
	for (j = 0; j < m; j++){
		fscanf_s(fp, "%d", &k);
		if (k == 0){
			fscanf_s(fp, "%s", st, 20);
			if (n1 == 0){
				a[n1] = (char**)malloc(sizeof(char*));

			}

			(*a)[n1] = (char*)malloc(sizeof(char)*(strlen(st) + 1));

			strcpy((*a)[n1], st);
			int h0 = 0, h1 = 0;
			fscanf_s(fp, "%d", &h0);
			if (n1 == 0){
				d[n1] = (int**)malloc(sizeof(int*));

			}

			(*d)[n1] = (int*)malloc(sizeof(int)*(h0));
			for (h1 = 0; h1 < h0; h1++){
				fscanf_s(fp, "%d", (**d + h1));
			}

			n1++;


		}
		else{
			fscanf_s(fp, "%s", st, 20);
			if (n2 == 0){
				b[n2] = (char**)malloc(sizeof(char*));

			}

			(*b)[n2] = (char*)malloc(sizeof(char)*(strlen(st) + 1));

			strcpy((*b)[n2], st);

			if (n2 == 0){
				c[n2] = (int**)malloc(sizeof(int*));

			}

			(*c)[n2] = (int*)malloc(sizeof(int)*(4));
			for (int n0 = 0; n0 < 4; n0++){
				fscanf_s(fp, "%d", (**c + n0));
			}


			n2++;
		}

	}
	tofree[0] = n1;
	tofree[1] = n2;
	tofree[2] = n2;
	tofree[3] = n1;
	fclose(fp);

}
こうなってます。
あと、66行目と91行目は思った通りに行ってないです…。
あと、No.13のコードを実行してみたら、ハンドルされないなんたらかんたら…とかで
i=0の時の、fscanf_s(fp, "%s", st);で止まっているみたいです(原因がさっぱりわからない…)

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

Re: テキストを表示させるプログラムでのアクセス違反

#19

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

ざんねん さんが書きました:あと、66行目と91行目は思った通りに行ってないです…。
多分、n1やn2の値にかかわらず(*d)[0]や(*c)[0]にアクセスしてしまっているからでしょう。
ざんねん さんが書きました:あと、No.13のコードを実行してみたら、ハンドルされないなんたらかんたら…とかで
i=0の時の、fscanf_s(fp, "%s", st);で止まっているみたいです(原因がさっぱりわからない…)
VC2008(cl)では再現できませんでしたが、fscanf_sの%sを使うときはバッファへのポインタの後にバッファサイズを指定する必要があるはずです。

コード:

#include "stdio.h"
#include"Share.h"
#include"stdlib.h"
#include "DxLib.h"
void load(char **&a, char **&b, int **&c, int **&d,int g[3]);
int tofree[4];
int main(void)

{
	int g[3] = {0, 0, 0};
	//int k; // unused?
	char **a = NULL, **b = NULL;
	int **c = NULL;
	int	**d = NULL;
	load(a, b, c, d, g);
	printf("%s\n", a[0]);
	printf("%s\n", b[0]);
	printf("%s\n", b[1]);
	for (int i = 0; i < g[1]; i++){
		delete[] a[i];
		delete[] c[i];
	}
	for (int i = 0; i < g[2]; i++){
		delete[] b[i];
		delete[] d[i];
	}
	delete[] a;
	delete[] b;
	delete[] c;
	delete[] d;
	return 0;

}
void load(char **&mn, char **&sn, int **&gd, int **&spd,int g[3]){
	FILE *fp;
	char st[1024];
	int n,i,k,n1=0,n2=0,m;
	
	fp = fopen("loadk.txt", "r");
	for (n = 0; n < 3; n++){
		fscanf_s(fp, "%d", g+n);
	}
	mn = new char*[g[1]];
	gd = new int*[g[1]];
	sn = new char*[g[2]];
	spd = new int*[g[2]];

	for (k = 0; k < g[0]; k++){
		fscanf_s(fp, "%d", &i);
		if (i == 0){
			fscanf_s(fp, "%s", st, (unsigned)(sizeof(st) / sizeof(st[0])));
			mn[n1] = new char[strlen(st)+1];
			strcpy(mn[n1], st);
			fscanf_s(fp, "%d", &m);
			gd[n1] = new int[m];
			for (n = 0; n < m; n++){
				// Wrong type!
				//fscanf_s(fp, "%d", gd+n1+n);
				fscanf_s(fp, "%d", *(gd+n1)+n);
			}
			n1++;
		}
		if (i == 1){
			fscanf_s(fp, "%s", st, (unsigned)(sizeof(st) / sizeof(st[0])));
			sn[n2] = new char[strlen(st) + 1];
			strcpy(sn[n2], st);
			spd[n2] = new int[4];
			for (n = 0; n < 4; n++){
				// Wrong type!
				//fscanf_s(fp, "%d", spd + n2 + n);
				fscanf_s(fp, "%d", *(spd + n2) + n);
			}
			n2++;
		}
	}
	

	fclose(fp);

}
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

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