free関数の解放について

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

free関数の解放について

#1

投稿記事 by たまのび » 13年前

はじめまして。たまのびと申します。

free関数の挙動について質問いたします。
現在作成中のプログラム(euclid.exe)は、誤り訂正符号に使うユークリッド復号法のプログラムです。コンパイルは通り、プログラム自体は期待する動作をしてくれます。しかし、main関数の最後にfree関数を入れると、エラーが出てプログラムが途中で終わってしまいます。free関数を入れなければエラーを出力せずに正常終了します。調べてみたところ、エラーの出る位置はfree関数の部分だと分かりました。しかし、なぜfree関数の部分でエラーが出るのかわかりません。
●エラー内容
[tab=30]問題が発生したため、euclid.exeを終了します。ご不便をおかけして申し訳ありません。
●やりたいこと・知りたいこと
[tab=30]free関数を入れた状態で、このプログラムが正常に(エラーなしで)終了するようにしたいです。また、free関数を入れることでなぜエラーが出るのか教えてください。
●C言語歴
[tab=30]C言語を始めてから5年目です。共用体を除き、ひと通り勉強してあります。
使用OS
[tab=30]Windows XP SP3
使用コンパイラ
[tab=30]Borland C++ 5.5.1
ライブラリ
[tab=30]ライブラリは使用しておりません。C言語標準関数と自作関数のみです。
以下が問題のソースコードです。長い間頭を悩ませましたが、どうしても解決しません。困っております。ソースコードが専門的で分かりづらいと思いますが、よろしくお願いします。

コード:

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

const int digit = 4;/*桁数*/
const int NUM = 256;/*行バッファの数*/

/*2進数を10進数へ*/
long bin2dec(const char *buff,int n){
	int i;
	long re = 0;
	for(i=0;i<n;i++){
		if( buff[i]=='1' )	re += pow(2,i);
	}
	return re;
}

int SearchedTable(int *tab,int n,int v){
	int index;
	int t;/*番兵*/
	
	if(v==0)return -1;
	t = tab[n-1];
	tab[n-1] = v;/*番兵*/
	for(index=0;tab[index]!=v;index++);/*探索*/
	if( index==n-1 ){
		if( t != v ) index = n;
	}
	tab[n-1] = t;/*番兵をもとに戻す*/
	return index;
}

/*応急処置的に、配列で関数を作る*/
int *polynominalDiv(int *dividend,int *divisor,int *quotient,int *remainder,int n_polynominal,int *table,int n_table){
	int n_dividend;/*割られる数の次数*/
	int n_divisor; /*割る数の次数*/
	int n_diff;    /*次数の差*/
	int i,m,k;
	
	if(    dividend==NULL || divisor==NULL || quotient==NULL || remainder==NULL
	    || n_polynominal<=0 || table==NULL     )return NULL;
	
	/*初期化*/
	for(i=0;i<n_polynominal;i++){
		quotient[i]  = 0;/*商*/
		remainder[i] = 0;/*あまり*/
	}
	
	/*割られる数の次数を計算*/
	for(i=n_polynominal-1;i>=0&&dividend[i]==0;i--);
	n_dividend = i;
	/*割る数の次数を計算*/
	for(i=n_polynominal-1;i>=0&&divisor[i]==0;i--);/**/
	n_divisor = i;
	/*次数差を計算*/
	n_diff = n_dividend - n_divisor;
	//printf("divisor:%d次 dividend:%d次 次数差:%d\n",n_divisor,n_dividend,n_diff);
	if( n_diff < 0 )return NULL;/*次数エラー*/
	/**/
	for(m=0;n_diff-m>=0;m++){
		int inv;/*逆数*/
		int index_inv;/*逆数の添字*/
		int index;
		int index_divisor;/*割る数の添字*/
		int index_dividend;/*割られる数の添字*/
		
		/*係数と対応する添字*/
		index_divisor  = SearchedTable(table,n_table,divisor[n_divisor]);
		index_dividend = SearchedTable(table,n_table,dividend[n_dividend-m]);
		if( index_divisor  == -1 )return NULL;/*エラー*/
		if( index_dividend == -1 )break;/*これ以上割れない*/
		//printf("divisor:[%2d]%d dividend:[%2d]%d\n",index_divisor,table[index_divisor],index_dividend,table[index_dividend]);
		
		/*係数がテーブルから見つからなければエラー*/
			if( index_divisor == n_table || index_dividend == n_table ){printf("テーブル参照エラー");return NULL;}
		
		index = ( (n_table-index_divisor)+index_dividend )%(n_table);
		index_inv = index;/*逆数の添字*/
		inv = table[index_inv];/*(割られる多項式の係数)/(割る多項式の最高次の係数)*/
		//printf("逆数:%d\n",inv);
		quotient[n_diff-m] = inv;
		dividend[n_dividend-m]=0;
		for(k=1;n_divisor-k>=0;k++){
			int index;
			int index_divisor = SearchedTable(table,n_table,divisor[n_divisor-k]);
			if( index_divisor == n_table ){printf("テーブル参照エラー");return NULL;}
			index = (index_inv+index_divisor)%n_table;
			//printf("%2d:%2d+[%2d]=",n_dividend-m-k,dividend[n_dividend-m-k],index);
			dividend[n_dividend-m-k] = (dividend[n_dividend-m-k]^table[index])&(n_table);/*割られる多項式のあまり*/
			//printf("%2d\n",dividend[n_dividend-m-k]);
		}
	}
	for(i=0;i<n_polynominal;i++){
		remainder[i]=dividend[i];
	}
	
	return remainder;
}

int main(){
	char *buff;
	const int NUM_ELEM = pow(2,digit)-1;/*テーブルの要素の数*/
	int t = 2;				/*誤り訂正能力*/
	int num_syndrome = 2*t;	/*シンドロームの数*/
	int *syndrome;			/*シンドローム*/
	int *table_alpha;		/*拡大体のテーブル*/
	int *t0=NULL;
	int *r0=NULL;
	int *t1=NULL;
	int *r1=NULL;
	int *t2=NULL;
	int *r2=NULL;
	int x;					/*テーブル作成に使う変数*/
	int i,j;				/*ループカウンタ*/
	long vd;				/*受信ベクトルの十進数表現*/
	int *v;		/*ベクトル*/
	int length;				/*受信ベクトルの長さ*/
	int error_flag;			/*誤りが存在するかどうか*/
	
	/*バッファ*/
	if( NULL == (buff = (char*)calloc(NUM,sizeof(char))) ){
		printf("バッファの領域確保に失敗。終了します。");
		return -1;
	}
	/*受信ベクトル*/
	if( NULL == (v = (int*)calloc(NUM,sizeof(char))) ){
		printf("受信ベクトルの領域確保に失敗。終了します。");
		return -1;
	}
	/*シンドローム*/
	if( NULL == (syndrome = (int*)calloc(num_syndrome,sizeof(int))) ){
		printf("シンドロームの領域確保に失敗。終了します。");
		return -1;
	}
	/*拡大体テーブル*/
	if( NULL == (table_alpha = (int*)calloc(NUM_ELEM,sizeof(int))) ){
		printf("拡大体テーブルの領域確保に失敗。終了します。");
		return -1;
	}
	if( NULL == (t0 = (int*)calloc((int)num_syndrome+1,sizeof(int))) ){
		printf("t0の領域確保に失敗。終了します。");
		return -1;
	}
	if( NULL == (r0 = (int*)calloc(num_syndrome+1,sizeof(int))) ){
		printf("r0の領域確保に失敗。終了します。");
		return -1;
	}
	if( NULL == (t1 = (int*)calloc(num_syndrome+1,sizeof(int))) ){
		printf("t1の領域確保に失敗。終了します。");
		return -1;
	}
	if( NULL == (r1 = (int*)calloc(num_syndrome+1,sizeof(int))) ){
		printf("r1の領域確保に失敗。終了します。");
		return -1;
	}
	if( NULL == (t2 = (int*)calloc(num_syndrome+1,sizeof(int))) ){
		printf("t2の領域確保に失敗。終了します。");
		return -1;
	}
	if( NULL == (r2 = (int*)calloc(num_syndrome+1,sizeof(int))) ){
		printf("r2の領域確保に失敗。終了します。");
		return -1;
	}
	r0[num_syndrome]=1;
	
	/*テーブル作成に使う初期値*/
	x = 1;
	/*テーブル作成*/
	for(i=0;i<NUM_ELEM;i++){
		if( x >> 4 )x^=3;/* a^4 + a^1 + 1 = 0*/
		x&=NUM_ELEM;
		table_alpha[i] = x;
		x <<= 1;
	}
	/*テーブル確認*/
	for(i=0;i<NUM_ELEM;i++){
		printf("%d\n",table_alpha[i]);
	}
	
	/*ベクトル*/
	printf("受信\n");
	vd=0;/*受信ベクトルの十進表現*/
	/*受信ベクトルを二進数入力*/
	fgets(buff,NUM,stdin);
	/*桁数をカウント*/
	for(i=0;buff[i]!='\n';length=++i);
	printf("受信ベクトルは%d桁\n",length);
	for(i=0;i<length;i++)
		v[i] = ( buff[i]=='1'?1:0 );/*文字から数値へ(2進数)*/
	vd = bin2dec(buff,length);/*二進数を十進数へ変換*/
	printf("受信ベクトル:%d\n",vd);
	printf("誤り訂正能力%d\n【シンドロームの計算】\n",t);
	for(j=1;j<=num_syndrome;j++){
		syndrome[j-1]=0;
			printf("syndrome[%2d] = ",j);
		for(i=0;i<length;i++){
			int k=(i*j)%NUM_ELEM;
			syndrome[j-1] ^= v[i] * table_alpha[k];
			if(v[i] == 1)
				printf("%2d+",table_alpha[k]);
		}
		syndrome[j-1] &= NUM_ELEM;
		printf(" = %2d",syndrome[j-1]);
		printf("\n");
	}
	
	error_flag=0;
	for(i=0;i<num_syndrome;i++){
		if(syndrome[i] != 0){
			error_flag = 1;/*誤りが存在する*/
			break;
		}
	}
	if(error_flag==0){printf("誤りはありません。\n");return 0;}
	
	printf("シンドローム多項式\n");
	for(i=0;i<num_syndrome;i++){
		r1[i] = syndrome[i];
		printf("r[%2d] %2d\n",i,r1[i]);
	}
	/*これ以降でエラーが発生します。*/
	free(&syndrome);
	free(&table_alpha);
	free(&t0);
	free(&r0);
	free(&t1);
	free(&r1);
	free(&t2);
	free(&r2);
	return 0;
}

アバター
a5ua
記事: 199
登録日時: 13年前

Re: free関数の解放について

#2

投稿記事 by a5ua » 13年前

freeの引数の&が不要です。
callocで返ってきた値をそのまま渡しましょう。

コード:

int *x = (int *)calloc(n, sizeof(int));
free(x);

たまのび

Re: free関数の解放について

#3

投稿記事 by たまのび » 13年前

無事解決いたしました。ありがとうございます。至極単純なミスでしたね。
5年もC言語をやっていて、このようなミスをしてしまうなんて恥ずかしい限りです。
今後も精進していきたいと思います。a5ua様ありがとうございました。

閉鎖

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