[C++]deleteの部分でプログラムが強制終了します。

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

[C++]deleteの部分でプログラムが強制終了します。

#1

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

通信系の研究室に所属しているたまのびという者です。誤り訂正符号について研究していて、シミュレーションのためにプログラムを作成することになりました。
■作成しようとしているプログラム
[tab=30]BCH符号を(ユークリッド)復号するプログラム。
■求める正常な動作
[tab=30]t_polynominalというnewで確保した変数をdeleteで解放します。
■問題点
[tab=30]コンパイルは通りますが、t_polynominalというnewで確保した変数をdeleteで解放する段階になるとプログラムが強制終了してしまいます。
■教えていただきたいこと
[tab=30]なぜdeleteの文でエラーが発生し、プログラムが強制終了してしまうのか。
■環境
[tab=30]OS:Windows XP SP3
[tab=30]コンパイラ:Borland C++ 5.5.1 for Win32
■C/C++言語歴
[tab=30]C言語歴:4年
[tab=30]C++歴:1年
[tab=30]C言語は共用体を除けば、ひととおりできますが、C++はある程度文法が分かる程度です。

■プログラムを実行する際の注意点
[tab=30]ソースコードをコンパイルし、起動すると入力を求められます。そのときは次の文字列を入力してください。
[tab=30]001100010110000
オフトピック
現在、多項式を配列にて表現しています。もしかすると、C++のvectorを使って実装したほうがいいのかもしれません。しかし、現在の方針でも作成できるはずだと考えています。現在の方針のままで、ソースコードのどこに手にいれればよいか教えていただけたら幸いです。
全体で300行ほどの長いコードですが、ご教授のほどよろしくお願い申し上げます。

下記がメインのソースコードです。printfデバッグがところどころに入っています。

コード:

#include<cstdio>
#include<cmath>
#include<iostream>
#include"euclid.h"

const int digit = 4;/*桁数*/
const int NUM = 256;/**/

int main(){
	using std::_streams;
	
	char buff[NUM] = {0,};
	int t = 2;/*誤り訂正能力*/
	int num_syndrome = 2*t;/*シンドロームの数*/
	int *syndrome;
	syndrome = new int[num_syndrome];/*シンドローム*/

	
	const int NUM_ELEM = std::pow(2,digit)-1;/*テーブルの要素の数*/
	int *table_alpha = new int[NUM_ELEM];/*有限体テーブル*/
	
	int x = 1;
	/*テーブル作成*/
	for(int 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(int i=0;i<NUM_ELEM;i++){
		std::printf("%d\n",table_alpha[i]);
	}
	/*ベクトル*/
	std::printf("受信\n");
	long vd=0;/*受信ベクトルの十進表現*/
	int v[NUM]={0,};
	std::fgets(buff,NUM,stdin);/*受信ベクトルを二進数入力*/
	int length;
	for(int i=0;buff[i]!='\n';length=++i);/*桁数*/
	std::printf("受信ベクトルは%d桁\n",length);
	for(int i=0;i<length;i++)
		v[i] = ( buff[i]=='1'?1:0 );
	vd = bin2dec(buff,length);/*二進数を十進数へ変換*/
	std::printf("受信ベクトル:%d\n",vd);
	std::printf("訂正能力%d\n【シンドロームの計算】\n",num_syndrome);
	for(int j=1;j<=num_syndrome;j++){
		syndrome[j-1]=0;
			std::printf("syndrome[%2d] = ",j);
		for(int i=0;i<length;i++){
			int k=(i*j)%NUM_ELEM;
			syndrome[j-1] ^= v[i] * table_alpha[k];
			if(v[i] == 1)
				std::printf("%2d+",table_alpha[k]);
		}
		syndrome[j-1] &= NUM_ELEM;
		std::printf(" = %2d",syndrome[j-1]);
		std::printf("\n");
	}
	
	int error_flag=0;
	for(int i=0;i<num_syndrome;i++){
		if(syndrome[i] != 0){
			error_flag = 1;
			break;
		}
	}
	if(error_flag==0){std::printf("誤りはありません。\n");return 0;}
	
	int **r_polynominal(NULL);/*あまり多項式*/
	int **q_polynominal(NULL);/*商多項式*/
	int **t_polynominal(NULL);/**/
	try{
		r_polynominal = new int*[2*t];/*あまり*/
		q_polynominal = new int*[2*t];/*商*/
		t_polynominal = new int*[2*t];
		for(int i=0;i<2*t;i++){
			r_polynominal[i] = new int[num_syndrome+1];
			q_polynominal[i] = new int[num_syndrome+1];
			t_polynominal[i] = new int[num_syndrome+1];
		}
	}
	catch( std::bad_alloc ){
		std::printf("領域の確保に失敗");
	}
	/*初期化*/
	for(int i=0;i<2*t;i++){
		for(int j=0;j<num_syndrome+1;j++){
			r_polynominal[i][j] = 0;
			q_polynominal[i][j] = 0;
			t_polynominal[i][j] = 0;
		}
	}
	r_polynominal[0][num_syndrome]=1;/* r0 = x^2t */
	t_polynominal[1][0]=1;
	
	std::printf("シンドローム多項式\n");
	for(int i=0;i<num_syndrome;i++){
		r_polynominal[1][i] = syndrome[i];/* r1 = S(x) */
		std::printf("%2d ",r_polynominal[1][i]);
	}	std::printf("\n");
	
	int n_poly=0;
	for(int i=2;;i++){
		/*多項式の割り算*/
		polynominalDiv(r_polynominal[i-2],r_polynominal[i-1],q_polynominal[i],r_polynominal[i],num_syndrome+1,table_alpha,NUM_ELEM);
		
		std::printf("R%2d\n",i);
		for(int j=2*t;j>=0;j--){
			std::printf("%2d ",r_polynominal[i][j]);
		}std::printf("\n");
		
		std::printf("Q%2d\n",i);
		for(int j=2*t;j>=0;j--){
			std::printf("%2d ",q_polynominal[i][j]);
		}std::printf("\n");
		
		#if 1
		/*多項式の掛け算*/
		if( false == (polynominalPro(t_polynominal[i-1],q_polynominal[i],t_polynominal[i],num_syndrome+1,table_alpha,NUM_ELEM))){
			return 0;
		}
		std::printf("T\n");
		for(int j=2*t;j>=0;j--){
			/*引き算*/
			t_polynominal[i][j] = (t_polynominal[i][j]^t_polynominal[i-2][j])&15;
			std::printf("%2d ",t_polynominal[i][j]);
		}	std::printf("\n");
		#endif
		
		int deg=0;/*次数*/
		for(int j=num_syndrome;j>=0;j--){/*次数検査*/
			/*多項式の係数を高次から探索*/
			if(r_polynominal[i][j]!=0){/*係数が0でなかったら*/
				deg = j;
				break;
			}
		}
		std::printf("多項式の次数は%d \n",deg);
		if(deg < t){
			n_poly=i;
			break;
		}
	}
	std::printf("before\n");
	for(int j=0;j<2*t;j++){
		for(int i=num_syndrome;i>=0;i--){
			std::printf("%2d ",t_polynominal[j][i]);
		}	std::printf("\n");
	}
	std::printf("after\n");
	
	/*誤り位置関数*/
	
	
	/*チェン探索*/
	
	
	std::printf("a");
	/*開放*/
	for(int i=0;i<2*t;i++){
		delete[] r_polynominal[i];
		std::printf("r");
		delete[] q_polynominal[i];
		std::printf("q");
		delete[] t_polynominal[i];
		std::printf("t");
		std::printf("%2d ",i);
	}
	std::printf("\nb");
	delete[] t_polynominal;
	delete[] q_polynominal;
	delete[] r_polynominal;
	delete[] syndrome;
	return 0;
}
以上がメインのコードとなります。
下記がeuclid.hのコードです。

コード:

/*2進数を10進数へ*/
long bin2dec(const char *buff,int n){
	using namespace std;
	long re = 0;
	for(int 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;
	
	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;
	//std::printf("divisor:%d次 dividend:%d次 次数差:%d\n",n_divisor,n_dividend,n_diff);
	if( n_diff < 0 ){/*割られる数より割る数の次数のほうが大きかったら*/
		//std::printf("割られる数より割る数の次数のほうが大きかった\n");
	}else{
		for(int 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 ){
				std::printf("添字エラー\n");
				return NULL;/*エラー*/
			}
			if( index_dividend == -1 )break;/*これ以上割れない*/
			//std::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 ){std::printf("テーブル参照エラー");return NULL;}
			
			index = ( (n_table-index_divisor)+index_dividend )%(n_table);
			index_inv = index;/*逆数の添字*/
			inv = table[index_inv];/*(割られる多項式の係数)/(割る多項式の最高次の係数)*/
			//std::printf("逆数:%d\n",inv);
			quotient[n_diff-m] = inv;
			dividend[n_dividend-m]=0;
			for(int 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 ){std::printf("テーブル参照エラー");return NULL;}
				index = (index_inv+index_divisor)%n_table;
				//std::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);/*割られる多項式のあまり*/
				//std::printf("%2d\n",dividend[n_dividend-m-k]);
			}
		}
	}
	for(int i=0;i<n_polynominal;i++){
		remainder[i] = dividend[i];
	}
	
	return remainder;
}
bool polynominalPro(const int *multiplicand, const int *multiplier,int *product,int n_polynominal,int *table,int n_table){
	int i;
	int n_multiplicand;
	int n_multiplier;
	for(i=n_polynominal-1;i>=0&&multiplicand[i]==0;i--);
	n_multiplicand = i;/*かけられる数の次数を計算*/
	for(i=n_polynominal-1;i>=0&&multiplier[i]==0;i--);
	n_multiplier = i;/*かける数の次数を計算*/
	
	if( (n_polynominal - 1)<(n_multiplicand + n_multiplier) ){
		std::printf("結果の次数が配列の長さを超えました。\n");
		return false;/*積が配列の上限を超える次数を持つ*/
	}
	
	for(int i=0;i<n_polynominal;i++){
		int index_multiplier = SearchedTable(table,n_table,multiplier[i]);/*かける数*/
		for(int j=0;j<n_polynominal;j++){
			int pro;/*積*/
			int index_pro;
			int index_multiplicand = SearchedTable(table,n_table,multiplicand[j]);/*かけられる数*/
			if( index_multiplicand == -1 || index_multiplier == -1 ){/*多項式の係数が0だった場合*/
				pro=0;
			}else{
				index_pro = (index_multiplier+index_multiplicand)&n_table;
				pro=table[index_pro];
			}
			product[i+j]=(product[i+j]^pro)&n_table;
		}
	}
	return true;
}
以上が、euclid.hのコードです。

アバター
ookami
記事: 214
登録日時: 15年前
住所: 東京都

Re: [C++]deleteの部分でプログラムが強制終了します。

#2

投稿記事 by ookami » 14年前

こんにちは。
とりあえず気づいた部分を...
polynominalPro関数の
product[i+j]=(product[i+j]^pro)&n_table;
の部分で、配列の範囲外に代入していませんか?

たまのび

Re: [C++]deleteの部分でプログラムが強制終了します。

#3

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

ookami さんが書きました:こんにちは。
とりあえず気づいた部分を...
polynominalPro関数の
product[i+j]=(product[i+j]^pro)&n_table;
の部分で、配列の範囲外に代入していませんか?
ookamiさん、ご指摘ありがとうございます。おっしゃるとおりです。とりあえずそこの部分を直してみようと思います。

たまのび

Re: [C++]deleteの部分でプログラムが強制終了します。

#4

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

たまのび さんが書きました:
ookami さんが書きました:こんにちは。
とりあえず気づいた部分を...
polynominalPro関数の
product[i+j]=(product[i+j]^pro)&n_table;
の部分で、配列の範囲外に代入していませんか?
ookamiさん、ご指摘ありがとうございます。おっしゃるとおりです。とりあえずそこの部分を直してみようと思います。
ookamiさんに指摘していただいたところを修正しましたところ、プログラムは所望する動作を致しました。
配列の領域外アクセスが原因だったようです。
このような原因によって、deleteでエラーが出ることがあるとは初めて知りました。
配列の領域外には注意したいと思います。

ookamiさんのおかげで解決に至りました。ありがとうございました。

たまのび

Re: [C++]deleteの部分でプログラムが強制終了します。

#5

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

解決したのに、解決にチェックを入れ忘れました。
改めて、ookamiさんありがとうございました。

閉鎖

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