C奇怪的数组分配行为

时间:2012-11-30 17:37:09

标签: c memory-management

我使用带有c的xcode,我对以下代码有一个奇怪的问题。

当算法到达我的conv函数中的y [k] = 0.0行然后x数组由0-s填充时,我必须理解为什么,我已经以我自己的方式纠正了这个错误。 当我在第二行注释并取消注释main函数中的第三行时,不会出现问题(见下文)。我知道我在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]);
    }
 }
}

3 个答案:

答案 0 :(得分:3)

将输出设置为指向大小为length的malloced数组。然后你使用它超越它。结果非常随机... 10 *长度的malloc什么都不做(泄漏内存除外),因为你在下一行覆盖它的返回值,返回值为generateSquareSignal ......

答案 1 :(得分: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个双精度的缓冲区的引用来覆盖对该内存的唯一引用。这会在第2行中分配内存时产生内存泄漏。

在第14行中,您告诉conv函数变量outputy内变为conv)可以存储200个双倍(和conv隐含地假设它可以存储至少那么多的数据)。这不是真的,因为它实际上指的是100个双打的块。结果是convoutputy引用的缓冲区范围之外写入,这会导致未定义的行为。 在您的情况下,未定义的行为恰好是溢出会在接下来分配的内存块中结束,这是input1x引用的内存块。

最后,bug的根本原因确实是generateSquareSignal中的新分配覆盖了output的先前分配。

答案 2 :(得分:1)

这里有很多问题......但大多数都是风格。真正的问题是你有一个内存泄漏的事实,这是导致你的问题。如果你要创建一个分配内存的函数,让它分配内存:

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

改变这两行代码:

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

将消除内存泄漏,并允许您的代码按照您的意愿正确调整(一个足够大的数组,可以达到1000倍)


只是为了好玩,这里有一些我正在考虑的其他几点:

  1. 当你只在那里存放200个时,为什么还需要1000个双打的空间?
  2. length似乎是一个常数,你可以把它变成一个全局的#define然后你不必担心传递它
  3. 如果您要传递长度,则无需将其传递两次至conv(),因为对input数组来说它是相同的
  4. 您可以通过仅将前200个位置记录到y
  5. ,无需在conv()循环中设置0.0