0

私はcでxcodeを使用していますが、次のコードで奇妙な問題が発生しています。

アルゴリズムがconv関数のy[k]= 0.0行に到達し、x配列が0で埋められると、理由を理解する必要があります。私はすでにこのエラーを独自の方法で修正しています。main関数で2行目をコメントし、3行目のコメントを外しても、問題は発生しません(以下を参照)。generateSquareSignalで配列を再割り当てすることは知っていますが、これがこのバグの理由ではないと思います。

 int length = 100;
 double *output = (double*) malloc(10 * length * sizeof(double));
 //double *output;
 output = generateSquareSignal(length);
 double *input1 = (double*) malloc(length * sizeof(double));
 double *input2 = (double*) malloc(length * sizeof(double));

 for (int i = 0; i < length; i++) {
        input2[i] = output[i];
        input1[i] = output[i];
                //printf("-%d=%lf\n",i ,input1[i]);
 }

 conv(input1, length, input2, length, output, 2 * length );


double* generateSquareSignal(int length) {

  printf("double* generateSquareSignal(int length)\n");

  double *signal = (double*) malloc(length * sizeof(double));

  int length_period = length / kPeriodSignal;
  for(int i=0; i < length; i++) {
    if (i % (length_period) < (length_period / 2)) {
        signal[i] = 1.0;
    } else {
        signal[i] = -1.0;
    }
    //printf("%d. - %lf\n", i, signal[i]);
 }

 return signal;
}



void conv( double *x,  int N_signal,
                         double *h, int N_kernel,
                         double *y, int N_output) {
int k;
for(k = 0; k < N_signal + N_kernel; k++) {
    y[k] = 0.0;
}

for (int i = 0; i < N_signal; i++) {
    printf("%lf-%lf\n", x[i], y[i]);
}


for(int i = 0; i < N_signal; i++) {
    for(int j = 0; j < N_kernel; j++) {
        double  xx = x[i];
        double  hh = h[j];
        double  yy = y[i + j];
        y[i + j] += x[i] * h[j];
        //printf("=%lf\n", y[i + j]);
    }
 }
}
4

3 に答える 3

3

問題はコードのこの部分にあります(行番号が追加されています)

 1 int length = 100;
 2 double *output = (double*) malloc(10 * length * sizeof(double));
 3 //double *output;
 4 output = generateSquareSignal(length);
 /* ... snipped line 5 to 12 */
13
14 conv(input1, length, input2, length, output, 2 * length );

2行目では、1000倍を保持するためにメモリを割り当てます。

4行目では、そのメモリへの唯一の参照を、100個のdoubleを保持するバッファへの参照で上書きします。これにより、2行目に割り当てられたメモリのメモリリークが発生します。

14行目convで、変数outputy内部になるconv)が200個のdoubleを格納できることを関数に指示します(そしてconv、少なくともその量のデータを格納できると暗黙的に想定します)。これは、実際には100個のdoubleのブロックを参照しているため、正しくありません。その結果、とconvによって参照されるバッファーの境界外に書き込みが行われ、未定義の動作が発生します。あなたの場合、未定義の振る舞いは、波及効果が次に割り当てられたメモリブロックに行き着くというものです。これはとによって参照されるものです。outputyinput1x

結局、バグの根本的な原因は、実際にで行われた新しい割り当てでgenerateSquareSignalあり、以前のの割り当てを上書きしますoutput

于 2012-11-30T18:13:53.047 に答える
3

長さのサイズのmalloced配列を指すように出力を設定します。次に、それを超えて使用します。結果はかなりランダムです...次の行の戻り値をgenerateSquareSignalの戻り値で上書きするため、10 *長さのmallocは何もしません(メモリリークを除く)。

于 2012-11-30T17:46:36.933 に答える
1

ここには多くの問題があります...しかし、それらのほとんどはスタイルです。本当の問題は、メモリリークがあり、それが問題を引き起こしているという事実です。メモリを割り当てる関数を作成する場合は、メモリを割り当てさせます。

double *output = (double*) malloc(10 * length * sizeof(double));
output = generateSquareSignal(length);

この 2 行のコードを次のように変更します。

double *output;
output = generateSquareSignal(10 * length);

そのメモリリークを排除し、コードを必要に応じて適切なサイズにすることができます (1000 double に十分な大きさの配列)


楽しみのために、私が考えている他のポイントのいくつかを次に示します。

  1. そこに200しか格納していないのに、なぜ1000倍のスペースが必要なのですか?
  2. length定数のように見えますが、それをグローバルな #define にすることができ、それを渡すことを心配する必要はありません
  3. 長さを渡す場合は、配列conv()でも同じであるため、に 2 回渡す必要はありません。input
  4. 最初の 200 スポットを memset するだけyで、ループに設定する必要がなくなります。conv()0.0
于 2012-11-30T18:42:48.063 に答える