メモリリークor領域アクセスが分かりません

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

メモリリークor領域アクセスが分かりません

#1

投稿記事 by syosinsya » 13年前

大学のプログラミングの課題で100の階乗を求め、表示するプログラムを作っているのですが
自分のパソコンではcygwinを使っていて、プログラムの動作確認はできたので
ネット提出で教授に提出したのですが
”実行時エラー:メモリリーク, 領域アクセスが適切に行われているか確認して下さい”
と返ってきます。
いろいろと試行錯誤をしたのですが、毎回同じ結果が返ってきます。
これ以上は僕には分からないです。助けてください。

プログラムは
varint型という10000進数で数値を扱うようにした型を作り、大きな桁の数値を扱っています。
もし、こうしたほうが良いよという点があればそれも教えてほしいです。
よろしくお願いします。

コード:

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

#define NUMDIGITS 50
typedef struct {
             int val[NUMDIGITS];
} varint;

varint vi_assign(long num);	/* long型の数値をvarint型に変換する */
int vi_keta(varint var);	/* 桁数を調べる */
varint vi_zero();			/* 値を0に初期化する */
void vi_print(varint var);	/* 値を表示する */

varint vi_add(varint a,varint b);	/* a+b */
varint vi_mul(varint a,varint b);	/* a*b */

int main(void){

	int i;
	varint ans=vi_assign(1);
	for(i=1;i<=100;i++)
		ans=vi_mul(ans,vi_assign(i));
	printf("%d!=",i-1);
	vi_print(ans);
	
	return 0;
}

varint vi_assign(long num){
	varint v=vi_zero();
	int i;
	for(i=0;num>0;i++){
		v.val[i]=num%10000;
		num=num/10000;
	}
	return v;
}

int vi_keta(varint var){
	int i=NUMDIGITS-1;

	while(var.val[i]==0)i--;

	return i+1;
}

varint vi_zero(){
	int i;
	varint v;

	for(i=0;i<NUMDIGITS;i++)v.val[i]=0;

	return v;
}

void vi_print(varint var){
	int i=vi_keta(var)-1;
	if(i<0)i=0;

	printf("%d",var.val[i]);
	i--;
	while(i>=0){
		printf("%04d",var.val[i]);
		i--;
	}
	printf("\n");
}

varint vi_add(varint a,varint b){
	int i,k;
	if(vi_keta(a)>=vi_keta(b))k=vi_keta(a);
	else k=vi_keta(b);

	for(i=0;i<k;i++){
		a.val[i]=a.val[i]+b.val[i];
		
		if(a.val[i]>=10000){
			a.val[i]=a.val[i]-10000;
			a.val[i+1]++;
		}
	}
	return a;
}

varint vi_mul(varint a,varint b){

	varint v=vi_zero(),seki=vi_zero();

	int i,j,ak=vi_keta(a),bk=vi_keta(b);

	for(i=0;i<bk;i++,v=vi_zero()){

		for(j=0;j<ak;j++){
			v.val[j+i]=a.val[j]*b.val[i]+v.val[j+i];

			if(v.val[j+i]>=10000){
				v.val[j+i+1]=v.val[j+i]/10000;
				v.val[j+i]=v.val[j+i]%10000;
			}
		}
		seki=vi_add(v,seki);
	}
	return seki;
}


アバター
へにっくす
記事: 634
登録日時: 13年前
住所: 東京都

Re: メモリリークor領域アクセスが分かりません

#2

投稿記事 by へにっくす » 13年前

NUMDIGITSが50なのにmainの中で100以下までやってるじゃない?
vi_assignに渡している引数で、valの添え字に使ってるよね。。
written by へにっくす

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

Re: メモリリークor領域アクセスが分かりません

#3

投稿記事 by box » 13年前

へにっくす さんが書きました:NUMDIGITSが50なのにmainの中で100以下までやってるじゃない?
vi_assignに渡している引数で、valの添え字に使ってるよね。。
val[]の添字に使っているのはあくまで i でありまして、num(階乗を求めたい数)を使っているわけではないですね。
質問者さんの発想は、おそらく、50個のint型配列の各要素に4桁ずつ格納して、
200桁まで対応できるようにしていると思います。
100! は200桁以内に収まりますので、特に問題ないような気がします。
バグのないプログラムはない。
プログラムは思ったとおりには動かない。書いたとおりに動く。

beatle
記事: 1281
登録日時: 14年前
住所: 埼玉
連絡を取る:

Re: メモリリークor領域アクセスが分かりません

#4

投稿記事 by beatle » 13年前

僕の環境(Mac OS X Lion 64 bits)では正常に動作しています(表面上は少なくともエラーが出ていません)。
一つ提案ですが、配列へのアクセスというアクセスすべてに、添字チェックのコードを付加したらどうでしょう。
assert(0 <= i && i < NUMDIGITS);
などというコードを、添字アクセスしている行の直前に書けばいいのです。
それで教授に動かしてもらい、どこで落ちたのか教えてもらうというのはいかがでしょうか。

アバター
へにっくす
記事: 634
登録日時: 13年前
住所: 東京都

Re: メモリリークor領域アクセスが分かりません

#5

投稿記事 by へにっくす » 13年前

box さんが書きました:
へにっくす さんが書きました:NUMDIGITSが50なのにmainの中で100以下までやってるじゃない?
vi_assignに渡している引数で、valの添え字に使ってるよね。。
val[]の添字に使っているのはあくまで i でありまして、num(階乗を求めたい数)を使っているわけではないですね。
質問者さんの発想は、おそらく、50個のint型配列の各要素に4桁ずつ格納して、
200桁まで対応できるようにしていると思います。
100! は200桁以内に収まりますので、特に問題ないような気がします。
あーなるほど
理解できました。

いや、メモリリークとか言ってるから、何となく先入観で答えてしまった…
ピントはずれな回答ですみません。

試しに私のところでコンパイルしても、ちゃんと通ってこんな結果が出ましたが。。

コード:

100!=93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000
written by へにっくす

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

Re: メモリリークor領域アクセスが分かりません

#6

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

syosinsya さんが書きました:”実行時エラー:メモリリーク, 領域アクセスが適切に行われているか確認して下さい”
と返ってきます。
難しいことが書いてありますが、要は所謂普通のRE(Runtime Error)ですよね?

vi_ketaで、var.valの全ての要素が0のとき、iが-1以下になってしまい、
場合によってはアクセス違反が発生します。
そして、そのようなケースは、実際にvi_mul内において、
iのループの最初の時に、vi_zero()を代入されたsekiを渡された
vi_add内で、vi_ketaが呼び出され、発生しています。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

閉鎖

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