2017-02-28 79 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 
}