C.“操纵”;“对象”;在功能上

C.“操纵”;“对象”;在功能上,c,pointers,C,Pointers,我又提出了另一个“为什么这样做有效,但这样做无效”的问题。我正在尝试构造我的C代码,以便能够增加复杂性并使用指向结构的指针,因此具有如下函数 Spline *new_spline() { \\code to set up "object" here Spline *toReturn = malloc(sizeof(*toReturn)); if (toReturn == NULL) perror("malloc toReturn failed in new

我又提出了另一个“为什么这样做有效,但这样做无效”的问题。我正在尝试构造我的C代码,以便能够增加复杂性并使用指向结构的指针,因此具有如下函数

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;
}
现在,当我尝试通过此函数修改样条曲线时,我的问题出现了:

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;
}
int-scale\u样条曲线(样条曲线*样条曲线,双比例\u-fac){
double*ys=malloc(样条曲线->直线*sizeof(*ys));
如果(ys==NULL){
printf(“比例误差_样条线()\n”);
出口(0);
}
对于(int i=0;iline;i++){
ys[i]=比例系数*样条曲线->y值[i];
}
样条曲线*toReturn=新的样条曲线(样条曲线->直线,样条曲线->x值,Y);
自由_样条(样条);
免费(ys);
*样条曲线=*t返回;
返回0;
}
最初没有错误,修改似乎有效,但随后代码中一个不相关的malloc()失败,导致segfault。我假设这是因为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;
}
int-scale\u样条曲线(样条曲线**样条曲线,双比例\u-fac){
double*ys=malloc((*样条线)->lines*sizeof(*ys));
如果(ys==NULL){
printf(“比例误差_样条线()\n”);
出口(0);
}
对于(int i=0;i<(*样条曲线)->直线;i++){
ys[i]=比例因子*(*样条)->y值[i];
}
样条曲线*toReturn=新的_样条曲线((*样条曲线)->直线,(*样条曲线)->x_值,ys);
自由_样条(*样条);
免费(ys);
*样条=返回;
返回0;
}
为什么scale_spline()的第一个版本不好,以及如何修改它以使其仍能使用样条线*?这段代码可能有很多错误,所以任何批评都是受欢迎的。谢谢大家!

注意:

new_spline(spline->lines, spline->x_vals, ys);
您没有复制
样条曲线->x_VAL
;您只是在新样条曲线中使用同一组x值!因此,如果使用
free_spline
释放旧样条曲线,则释放x值,如果释放新样条曲线,则x值已被释放,从而导致问题

要复制它,请添加新的样条曲线:

double *x_valsnew= malloc(lines, sizeof(double)); // or xmin?
memcpy(x_valsnew, x_vals, lines*sizeof(double));

(分配多少行可能与
行不同,这取决于您。关键是您必须分配新内存并复制。)

在第二个函数中,使用指针指向指针,您可以更改输入指针指向的位置。当函数被执行时,输入指针获取该函数外部的实际新值

如果仅在末尾执行,则第一个函数可以工作
spline=toReturn
,但由于
spline
是作为参数复制的值,因此此函数之外的值没有意义

使用双指针,您可以实现更改指针指向函数外部的位置。

问题在于:

free_spline(spline);
free(ys);
*spline = *toReturn;
在<代码>自由_样条(样条)
,您明确地以调用
free(spline)
结束。因此,您已经完全释放了
样条曲线
最初指向的位置。当您稍后将
toReturn
作为结构副本复制到
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\u vals
发生了变化:

    free(spline->y_vals);
    spline->y_vals = ys;
    return 0
}

请张贴真实代码
\\
不是注释介绍人,您的意思是
/
。请发布一个完整的示例。因为这看起来可疑:
toReturn->x_vals=x_vals\\double*
无论
\\
注释是什么,
x\u vals
从哪里来?你是
自由的
ing
x\u vals
y\u vals
系数,但不要在任何地方分配它们。这是个问题。除非您完全确定全局变量是合适的,否则不要使用全局变量。不仅仅是为了避免向函数传递参数,或者避免在函数中声明参数。请注意,当您有全局变量时,调试要困难得多,而且代码更难阅读,更重要的是,很容易引入错误。