C:free()无效指针;无需更改地址

时间:2015-06-21 15:49:00

标签: c free

我使用C(不是C ++)并收到以下错误:
Error in './c_rk4': free(): invalid pointer: 0x0000000000a911c0

我能够将错误追溯到第(1)和(2)行。如果我注释掉我标记的行,则不会发生(1)中的错误。所有其他free()用法都不会产生错误,如果我用free()注释掉所有行,程序就会运行。

我使用printf("%p\n", y_n);这样的行检查y_n之后malloc()之前和free()之前的地址是否相同(以及错误消息中的地址)。< / p>

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <complex.h>

void odesolver_rk4 (void (*)(double, _Complex double *, _Complex double **),
            int, double,
            int, _Complex double *, _Complex double ***);
void testfunc (double, _Complex double *, _Complex double **);

int main (int argc, char *argv[argc]) {  
  const int t_num = 300;
  const int y_num = 2;

  _Complex double **y_res;
  y_res = malloc(t_num*sizeof(_Complex double *));
  for (int i = 0; i < t_num; i++)
    y_res[i] = malloc(y_num*sizeof(_Complex double));

  odesolver_rk4(testfunc, t_num, 20.0, y_num, (_Complex double []){1.0, 0.0}, &y_res);

  for (int i = 0; i < t_num; i++) {
    for (int j = 0; j <= y_num; j++) {
      printf("%f %f ", creal(y_res[i][j]), cimag(y_res[i][j]));
    }
    printf("\n");
  }

  for (int i = 0; i < t_num; i++)
    free(y_res[i]); // error (2)
  free(y_res);

  return 0;
}


void odesolver_rk4 (void (*func)(double, _Complex double *, _Complex double **),
            int t_num, double t_end,
            int y_num, _Complex double *y_start, _Complex double ***y_res) {
  double t_step = t_end/t_num;

  double t_n = 0;
  _Complex double *y_n, *y_A, *y_B, *y_C;
  _Complex double *dy_n, *dy_A, *dy_B, *dy_C;

  y_n = malloc(y_num*sizeof(_Complex double));
  y_A = malloc(y_num*sizeof(_Complex double));
  y_B = malloc(y_num*sizeof(_Complex double));
  y_C = malloc(y_num*sizeof(_Complex double));

  dy_n = malloc(y_num*sizeof(_Complex double));
  dy_A = malloc(y_num*sizeof(_Complex double));
  dy_B = malloc(y_num*sizeof(_Complex double));
  dy_C = malloc(y_num*sizeof(_Complex double));

  for (int j = 0; j < y_num; j++)
    y_n[j] = y_start[j];

  (*y_res)[0][0] = t_n;
  for (int j = 0; j < y_num; j++)
    (*y_res)[0][j + 1] = y_start[j];
  for (int i = 1; i < t_num; i++) {
    func(t_n, y_n, &dy_n);
    for (int j = 0; j < y_num; j++)
      y_A[j] = y_n[j] + dy_n[j]*t_step/2;

    func(t_n + t_step/2, y_A, &dy_A);
    for (int j = 0; j < y_num; j++)
      y_B[j] = y_n[j] + dy_A[j]*t_step/2;

    func(t_n + t_step/2, y_B, &dy_B);
    for (int j = 0; j < y_num; j++)
      y_C[j] = y_n[j] + dy_B[j]*t_step;

    func(t_n + t_step, y_C, &dy_C);
    for (int j = 0; j < y_num; j++) {
      y_n[j] += t_step/6*(dy_n[j] + 2*(dy_A[j] + dy_B[j]) + dy_C[j]);

      (*y_res)[i][0] = t_n;
      (*y_res)[i][j + 1] = y_n[j]; // something goes wrong here for (1)
    }

    t_n += t_step;
  }

  free(y_n); // error (1)
  free(y_A);
  free(y_B);
  free(y_C);

  free(dy_n);
  free(dy_A);
  free(dy_B);
  free(dy_C);
}

void testfunc (double t, _Complex double *y, _Complex double **dy) {
  (*dy)[0] = -y[1];
  (*dy)[1] = y[0];
}

1 个答案:

答案 0 :(得分:2)

问题在于这个循环:

for (int j = 0; j < y_num; j++)

和这行代码:

(*y_res)[i][j + 1] = y_n[j]

您的循环必须为j < y_num - 1,或者您的表达式应使用[j]。否则,您将越过y_res数组的末尾。执行此操作时,您将覆盖y_n分配的malloc标头,这就是free()之后抱怨它是无效指针的原因。

顺便说一句,valgrind是找到这类问题的好工具。

http://valgrind.org

评论中还建议使用AddressSanitizer:

http://clang.llvm.org/docs/AddressSanitizer.html