2017-02-28 80 views
0

我回到了另一个“为什么这个工作,但这不”问题。我试图构建我的C代码,以便能够建立复杂性和指针结构工作,因此像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; 
} 

有最初没有误差和修饰似乎工作,但不相关的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()不好,如何修改它仍与样条线的工作*的第一个版本?这段代码可能有很多错误,所以任何批评都会受到欢迎。谢谢!

+1

请张贴实际的代码。 '\\'不是评论介绍人,你的意思是'//'。 – unwind

+1

并发布*完整*示例。因为这看起来很可疑:'toReturn-> x_vals = x_vals; \\ double *'Nevermind the'\\''comment“,'x_vals'从哪里来? –

+0

你'''''''免费''''''''y_vals','coeffs',但不要将它们分配到任何地方。这是一个问题。 –

回答

0

注意搭配:

new_spline(spline->lines, spline->x_vals, ys); 

复制spline->x_vals;你只是在新样条中使用相同的一组x值!因此,如果释放旧样本的free_spline,则释放x值,如果释放新样条线,则x值已释放,从而导致出现问题。

要复制它,加入new_spline:(有多少分配可以从lines不同;这是给你的一点是,你必须分配新的内存和复印件)

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

0

在指针指针的第二个函数中,您将输入指针更改为指向的位置。当执行函数时,输入指针会在此函数之外获得实际的新值。

如果您最后只做spline = toReturn,但由于spline被复制为参数值,所以第一个函数可以工作,但此函数外的值没有意义。

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

0

的问题就在这里:

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发生了变化:

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