2012-07-15 112 views
2

我想弄清楚爲什麼我的程序在調用ll_print時崩潰了。 [這是一個非常簡單和直接的問題,我不知道是什麼,真正加入到填補缺口解釋]鏈接列表 - C - 分段錯誤

struct ll{ 
      struct ll* next; 
      int n; 
     } ll; 

    void ll_print(struct ll *l){ 
     while (l) { 
     printf("%d ", l->n); 
     l=l->next; 
     } 
    } 

    void ll_fill(struct ll *l, int n){ 
     struct ll *temp= NULL; 
     while (n>0){ 
     l= (struct ll*)malloc(sizeof(struct ll)); 
     l->n=n; 
     l->next= temp; 
     temp=l; 
     n--; 
     } 
    } 

    int main(void){ 
     int i=0; 
     struct ll *l;                                   
     ll_fill(l, 10); 
     ll_print(l); /** causing a segmntation fault **/                                         
    } 

回答

5

這是因爲l指針永遠不會初始化。看起來你期望ll_fill初始化它,但你錯了 - 它是通過值傳遞(通過複製),並且任何你分配給lll_fill函數都不會爲在main內部聲明的l賦值。爲了實現你想要的,通過指針傳遞l(你將有指向指針的指針)。或者,使其返回值爲ll_fill,並執行l = ll_fill(l, 10);。此外,讓自己一個調試器 - 它會幫助你很多。

+0

您的解決方案工作很好,但我仍然困惑爲什麼我不得不將指針傳遞給指向ll_fill函數的指針。不傳遞單個指針意味着我們將內存中該結構的實際地址傳遞給該函數?不改變它的價值會導致改變它指向的實際價值? – Smokie 2012-07-15 06:43:23

+1

@Smokie:它的確如此,但你也想在某處存儲一個結果,讓'l'在'main'內部聲明''看到'變化'。如果您更改通過「按值」傳遞的指針的值,則調用者將看不到更改。 – 2012-07-15 06:48:20

1

您沒有在您的main()函數中填充指向本地變量l的指針。相反,您在ll_fill()函數中填充了l的參數。考慮讓ll_fill返回malloc的指針的值。

+0

出於練習目的,我想通過l並通過指針進行初始化。在這些情況下返回是否不僅僅是好的做法? – Smokie 2012-07-15 06:34:30

+0

那麼在這種情況下,你並不是真正閱讀指針,只是寫它,所以它不需要是你的函數的參數,只是一個返回值。 – 2012-07-15 06:37:25

+0

明白了,但通過指針傳遞它或僅初始化一個新列表並返回它之間有什麼區別?我已經看到POSIX函數中存在這兩種類型。就實踐而言,它是否很好? – Smokie 2012-07-15 06:46:31

1

當你撥打ll_fill(l, 10); - 問問自己,l的價值是多少?當然你可以在被調用的函數中創建一個新的對象 - 但是你的main()怎麼知道這個新對象呢?它仍然指向最初(隨機)分配給本地變量l未初始化的內存。

嘗試指派NULL爲初始值您l

struct ll *l = NULL; 
1

您在通話BYY價值的概念只是混淆。您通過值傳遞指針傳遞給函數ll-fill。但是ll-fill會自行創建副本,無論它做什麼改變,它都不會對主函數的指針產生任何影響。所以當你將它傳遞給ll_print()時,因爲它沒有被初始化,所以打印這個值只會給你分段錯誤。
使用調試器它會幫助你始終處於這種狀態。

1

由於您正在爲函數內的指針l分配內存,所以您需要傳遞指針的地址而不是傳遞指針變量。儘管指針l在功能ll_fill內初始化,但範圍在功能出來時死亡,並且ll_print(l)引發段錯誤,因爲它找不到指針l的地址。

解決方案:

  1. 傳遞指針的地址,如果想在函數內部初始化。

  2. 如果指針由一個超過它總是好的兩個功能的共同範圍申報(也就是內main()初始化)

1

更改ll_fill函數定義和共享調用如下:

void ll_fill(struct ll **l, int n){ 
    struct ll *temp= NULL; 
    while (n>0){ 
    *l= (struct ll*)malloc(sizeof(struct ll)); 
    (*l)->n=n; 
    (*l)->next= temp; 
    temp=(*l); 
    n--; 
    } 
} 

int main(void){ 
    int i=0; 
    struct ll *l;                 
    ll_fill(&l, 10); 
    ll_print(l); /** now no segmntation fault :) **/        
}