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&÷nd[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;
}