我回到了另一个“为什么这有效,但这不是”问题。我正在尝试构建我的C代码,以便能够建立复杂性并使用指向结构的指针,因此具有像
这样的函数console.log
并且等效地
Spline *new_spline() {
\\code to set up "object" here
Spline *toReturn = malloc(sizeof(*toReturn));
if (toReturn == NULL) perror("malloc toReturn failed in new_spline()\n");
toReturn->x_vals = x_vals; \\double*
toReturn->y_vals = y_vals; \\double*
toReturn->coeffs = coeffs; \\double*
toReturn->lines = lines; \\int
toReturn->xmin = xmin; \\double
toReturn->xmax = xmax; \\double
return toReturn;
}
现在,当我尝试通过此函数修改样条线时出现问题:
int free_spline(Spline *s) {
free(s->x_vals);
free(s->y_vals);
free(s->coeffs);
free(s);
s = NULL;
return 0;
}
最初没有错误,并且修改似乎有效,但是随后的一个不相关的malloc()会在代码中失败,从而产生段错误。我假设这是因为free_spline()后跟* spline = * toReturn不能做我想要的,这是为了使这个指针指向* toReturn指向的数据。这个函数的版本是:
int scale_spline(Spline *spline, double scale_fac) {
double *ys = malloc(spline->lines * sizeof(*ys));
if (ys == NULL) {
printf("err in scale_spline()\n");
exit(0);
}
for (int i = 0; i < spline->lines; i++) {
ys[i] = scale_fac * spline->y_vals[i];
}
Spline *toReturn = new_spline(spline->lines, spline->x_vals, ys);
free_spline(spline);
free(ys);
*spline = *toReturn;
return 0;
}
为什么scale_spline()的第一个版本确实不好以及如何修改它仍然可以使用Spline *?这段代码可能有很多错误,所以任何批评都会受到欢迎。谢谢!
答案 0 :(得分:0)
请注意:
new_spline(spline->lines, spline->x_vals, ys);
你不复制spline->x_vals
;您只是在新样条曲线中使用相同的x值集!因此,如果您使用free_spline
释放旧样条线,则释放x值,如果释放新样条线,则x值已经被释放,从而导致出现问题。
要复制它,请添加new_spline
:
double *x_valsnew= malloc(lines, sizeof(double)); // or xmin?
memcpy(x_valsnew, x_vals, lines*sizeof(double));
(分配的数量可能与lines
不同;这取决于您。关键是您必须分配新的内存和副本。)
答案 1 :(得分:0)
在带指针指针的第二个函数中,你可以改变它所指向的输入指针。执行函数时,输入指针在此函数之外获得实际的新值。
如果你最后只做spline = toReturn
,那么第一个函数可以工作,但因为spline
被复制为参数值,所以此函数之外的值没有任何意义。
使用双指针,您可以实现更改指针指向函数外的位置。
答案 2 :(得分:0)
问题在于:
gradle tasks
在free_spline(spline);
free(ys);
*spline = *toReturn;
中,您明确地以调用free_spline(spline);
结束。所以你已经完全释放free(spline)
最初指向的地方。当您稍后将spline
复制到toReturn
作为结构副本时,您会复制到悬空指针,即未定义行为。如果您只想修改原始spline
结构,则应该执行以下操作:
Spline
或者只有 Spline *toReturn = new_spline(spline->lines, spline->x_vals, ys); // compute new spline
free(spline->x_vals); // free internals of original one
free(spline->y_vals);
free(spline->coeffs);
free(ys); // free intermediate array
*spline = *toReturn; // copy the internals to original spline
free(toReturn); // free the temp one
return 0;
}
发生了变化:
y_vals