我使用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];
}
答案 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是找到这类问题的好工具。
评论中还建议使用AddressSanitizer: