[C++]deleteの部分でプログラムが強制終了します。
Posted: 2011年8月26日(金) 02:49
通信系の研究室に所属しているたまのびという者です。誤り訂正符号について研究していて、シミュレーションのためにプログラムを作成することになりました。
■作成しようとしているプログラム
[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
全体で300行ほどの長いコードですが、ご教授のほどよろしくお願い申し上げます。
下記がメインのソースコードです。printfデバッグがところどころに入っています。
以上がメインのコードとなります。
下記がeuclid.hのコードです。
以上が、euclid.hのコードです。
■作成しようとしているプログラム
[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を使って実装したほうがいいのかもしれません。しかし、現在の方針でも作成できるはずだと考えています。現在の方針のままで、ソースコードのどこに手にいれればよいか教えていただけたら幸いです。
下記がメインのソースコードです。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&÷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;
//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;
}