C在函数中操纵“对象”

时间:2017-02-28 12:52:38

标签: c pointers

我回到了另一个“为什么这有效,但这不是”问题。我正在尝试构建我的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 *?这段代码可能有很多错误,所以任何批评都会受到欢迎。谢谢!

3 个答案:

答案 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