2013-09-30 90 views
0

我目前在C大學學習數據結構程序,現在我遇到了很多麻煩。我想澄清,我所要求的幫助不是爲了標記,只是練習挑戰問題。分段錯誤錯誤 - 使用鏈接列表實現堆棧

目標是使用鏈接列表實現堆棧。通過閱讀講座筆記,我認爲我已經完成了大部分功能。我需要演示Push()和Pop()將附加和假裝。使用Cygwin,我編譯沒有錯誤。但是當我嘗試運行它時,出現「分段錯誤」。這是什麼意思,我該如何解決?如果我刪除「stack = initLListStack();」,錯誤消失。這裏是我的代碼:

#include <stdio.h> 
#include <stdlib.h> 

typedef struct Link{ 
int *value; 
struct Link *next; 
}Link; 

typedef struct LList1{ 
int *size; 
Link *head; 
}LList1; 

typedef struct LListStack{ 
LList1 *llist; 
}LListStack ; 


LListStack *initLListStack(void) 
{ 
LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ; 
stack->llist->size = 0; 
stack->llist->head = NULL; 
return(stack); 
} 


void removefront(LList1 *llist) 
{ 
if(llist->head != NULL){ 
    llist->head = llist->head->next; 
    llist->size--; 
} 
} 

Link *FindLastLink(LList1 *llist, Link *link) 
{ 
if(link = NULL){ 
    return(NULL); 
} 
else if(link->next == NULL){ 
    return(link); 
} 
else{ 
    return(FindLastLink(llist, link->next)); 
} 
} 

Link *FindSecondLastLink(LList1 *llist, Link *link) 
{ 
if(link = NULL){ 
    return(NULL); 
} 
else if(link->next->next == NULL){ 
    return(link); 
} 
else{ 
    return(FindSecondLastLink(llist, link->next)); 
} 
} 

void removelast(LList1 *llist) 
{ 
Link *secondlastlink = (Link *) malloc(sizeof(Link)); 
secondlastlink = FindSecondLastLink(llist, llist->head); 
secondlastlink->next = NULL; 
llist->size--; 

} 



void prepend(int *newValue, LList1 *templist) 
{ 
Link *node = (Link *) malloc(sizeof(Link)); 
node->value = newValue; 
node->next = templist->head; 
templist->head = node; 
templist->size++; 
} 

void append(int *newValue, LList1 *templist) 
{ 
Link *node = (Link *) malloc(sizeof(Link)); 
Link *lastlink = (Link *) malloc(sizeof(Link)); 
lastlink = FindLastLink(templist, templist->head); 
node->value = newValue; 
lastlink->next = node; 
node->next = NULL; 
templist->size++; 
} 

void prepush(int *value, LListStack *stack) 
{ 
prepend(value, stack->llist); 
} 

void apppush(int *value, LListStack *stack) 
{ 
append(value, stack->llist); 
} 

int prepop(LListStack *stack, int *value) 
{ 
int result ; 

if ((!isEmpty(stack))) 
{ 
    removefront(stack->llist); 
    result = 1 ; 

} 
else { 
    result = 0 ; 
} 
return(result) ; 
} 

int isEmpty(LListStack *stack) 
{ 
int empty; 

if (stack->llist->head == NULL) 
    return(1) ; 
else 
    return(0) ; 
} 

int apppop(LListStack *stack, int *value) 
{ 
int result ; 

if ((!isEmpty(stack))) 
{ 
    removelast(stack->llist); 
    result = 1 ; 
} 
else 
    result = 0 ; 

return(result) ; 
} 

//*******MAIN**********// 

int main() 
{ 
LListStack *stack = (LListStack *) malloc (sizeof(LListStack)); 

stack = initLListStack(); //if I take this away, I can run the program 


return(0); 
} 

我沒有那麼多的Main(),因爲我只是想讓它先運行。初始化堆棧似乎是問題所在。

感謝您的幫助!

回答

1

的問題是在你的initLListStack()功能:

LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ; 
stack->llist->size = 0; 
stack->llist->head = NULL; 
return(stack); 

malloc結果是內存大到足以容納一個LListStack結構的初始化塊。

您對該內存所做的第一件事是讀取其llist成員。由於這是未初始化的,因此您會調用未定義的行爲,幸運的是,會導致段錯誤。 (當發生這種情況時,編譯器會在規範中向我們的教師發送令人尷尬的電子郵件。)

您需要初始化llist,然後才能在堆棧中使用該成員。喜歡的東西:

LListStack *stack = malloc(sizeof(*stack)); 
stack->llist = malloc(sizeof(*stack->llist)); 
stack->llist->size = 0; 
stack->llist->head = NULL; 
return stack; 

請注意,我也去掉了一些不必要的鑄件和括號,並改變了sizeof操作符來計算,你需要根據你存儲到指針的內存。

+0

非常感謝!這工作。只是一個問題1)我看到你在malloc之前拿出了「(LListStack *)」。那是什麼意思?我的教授一直告訴我們要把它包含在malloc之前,但我不確定它做了什麼,因爲我讀過的每個地方都沒有這樣做。 – dvdmarc12

+1

你是一名教授,顯然是靠C++來生活,或者如果你的程序沒有正確設置,就不會考慮*非必需*轉換可以做的所有事情。標準C不需要從'void *'轉換爲任何其他指針類型。 [不要在標準C中投射malloc的結果](http://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc)。 – WhozCraig

0
LListStack *initLListStack(void) 
{ 
    LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ; 
    stack->llist->size = 0; // **this is probably where it crashes** 
    stack->llist->head = NULL; 
    return(stack); 
} 

您分配stack不錯,但你不分配stack->llist。因此stack->llist未初始化,然後在stack->llist->size中將其解除引用。解除引用 未初始化的變量會導致未定義的行爲。

爲了解決這個問題,分配重新建立了新>列表是這樣的:

LListStack *initLListStack(void) 
{ 
    LListStack *stack = (LListStack *) malloc(sizeof(LListStack)) ; 
    stack->llist = (LListStack *) malloc(sizeof(LList1)) ; // ADD THIS LINE 
    stack->llist->size = 0; 
    stack->llist->head = NULL; 
    return(stack); 
} 
0

分段錯誤通常是由試圖取消引用未初始化的指針而引起的。在你的情況下,你已經在initLListStack方法中爲stack分配了內存,但是你尚未初始化它 - 特別是llist字段未初始化爲任何特定值。您需要分配LList1並將llist字段設置爲新分配的內存。