2015-03-31 59 views
2

如果這是一個易於修復的問題,我真的很抱歉,但我是一個初學者。 我有一個任務將一些函數寫入stack-struct。結構被給出了。我不能擺脫push()行「s->元素中的分段錯誤...」 我不知道什麼是錯誤的小時後搜索和搜索。C - 結構化分段錯誤

下面的代碼:

#define STACK_SIZE 5

#include <stdio.h> #include <stdlib.h> typedef struct stackADT { int elements[STACK_SIZE]; int count; } stack; void initialize(stack *s) { stack *newStack; newStack = malloc(sizeof(*newStack)); newStack->count = 0; s = newStack; } int push(stack *s, int value) { if(s->count == 5) return -1; else { s->elements[s->count++] = value; return s->elements[s->count-1]; } } int main() { stack* sA; stack* sB; initialize(sA); initialize(sB); printf("%d\n",push(sA,3)); return 0; }
+2

@Mirko Richter爲什麼你動態地分配一個棧類型的對象?你可以簡單地定義一個像堆棧sA的堆棧;還有函數初始化什麼都沒有。:) – 2015-03-31 18:34:10

+0

好的。我怎樣才能改變函數初始化初始化?;) – mikefedi 2015-03-31 18:37:58

回答

2

我認爲你需要像下面

#include <stdio.h> 

#define STACK_SIZE 5 

typedef struct stackADT 
{ 
    int elements[STACK_SIZE]; 
    int count; 
} stack; 

void initialize(stack *s) 
{ 
    s->count = 0; 
} 

int push(stack *s, int value) 
{ 
    return s->count == STACK_SIZE ? -1 : (s->elements[s->count++] = value); 
} 

int main(void) 
{ 
    stack sA; 
    stack sB; 

    initialize(&sA); 
    initialize(&sB); 

    printf("%d\n", push(&sA, 3)); 

    return 0; 
} 
2

因爲你是按值傳遞兩個指針(所以你實際上是傳遞指針的拷貝),初始化功能更改爲int initilize(stack **s)s = newStack;*s = newStack;然後調用初始化像這initialize(&sA); initialize(&sB);

你真的不應該動態分配對象,除非你必須,你也不是你分配的內存,這是一個內存泄漏。

+0

謝謝,這個工程!我拿到指針副本的部分。在賦值中,函數initialize被定義爲initialize(stack * s)。是否有可能像這樣分配內存? – mikefedi 2015-03-31 18:46:15

+0

@mikefedi我不這麼認爲,一定是錯字 – 2015-03-31 18:47:42

2

當您將指針傳遞給某個函數時,函數會收到指針的副本。這通常很好,除非你是改變/創建指針的START地址

在你的情況下,sAsB不包含地址(當你將它們傳遞給initialize時它們沒有指針)。所以你的initialize函數必須把指針的地址而不是指針本身指定一個地址給在main中可見的指針。例如:

void initialize(stack **s) 
{ 
    stack *newStack; 
    newStack = malloc(sizeof(*newStack)); 
    newStack->count = 0; 

    *s = newStack; 
} 

... 

initialize (&sA); 

解引用上述雙指針**s,(例如*s = newStack;),分配的newStack作爲指針s的值的地址。

我也建議檢查分配分配的newStack*s位置之前成功:

void initialize(stack **s) 
{ 
    stack *newStack; 
    if (!(newStack = malloc(sizeof(*newStack)))) { 
     fprintf (stderr, "%s() error: memory allocation failed.\n", __func__); 
     exit (EXIT_FAILURE); 
    } 
    newStack->count = 0; 

    *s = newStack; 
} 
0

您收到一個分割因爲您試圖將push()中的值分配給未分配的內存區域。 initialize()可以成功分配內存並使用count = 0對其進行初始化,但您的任務分配爲s = newStack不起作用。正如大衛和亞歷杭德羅指出的,你正在傳遞「指針的副本」。本質上,你傳遞的是未初始化的變量的地址,但是你沒有通過函數來​​用新地址更新該變量。你需要傳遞一個指向堆棧指針的指針。 (也稱爲二級指針。)這意味着initialize()將接收保存堆棧結構的內存地址的變量的內存地址。因此,該函數可以將二級指針的指針對地址分配給malloced堆棧。

也許這會更容易通過簡單地看代碼來理解:

#define STACK_SIZE 5 

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

typedef struct stackADT { 
    int elements[STACK_SIZE]; 
    int count; 
} stack; 

void initialize(stack **s) 
{ 
    stack *newStack; 
    newStack = malloc(sizeof(*newStack)); 

    if(NULL == newStack){ 
     // Malloc could not allocate memory 
     // for newStack. 
     // Set s to NULL to indicate the error 
     s = NULL; 
     // Return prematurely 
     return; 
    } // else, malloc succeeded 

    newStack->count = 0; 

    // Assign the value of the malloced stack pointer to the pointee of stack **s 
    *s = newStack; 
} 

int push(stack *s, int value) 
{ 
    if(s->count == STACK_SIZE){ 
     // Stack has too many elements. 
     // Return with error value (-1) 
     return -1; 
    } else { 
     // Assign the new value to the current last index 
     s->elements[s->count] = value; 
     // Add count to indicate a new variable has been added 
     s->count++; 
     // Use the array to return the value just added 
     return s->elements[ (s->count - 1) ]; 
    } 
} 

int main() 
{ 
    stack* sA; 
    stack* sB; 

    // Send the function a pointer to the stack pointer 
    initialize(&sA); 
    initialize(&sB); 

    if(sA == NULL){ 
     puts("Could not allocate the memory for stack variable sA.\n"); 
     return -1; 
    } 

    printf("%d\n", push(sA, 3)); 

    // Clean up the memory 
    free(sA); 
    free(sB); 

    return 0; 
} 

我還修改了代碼稍有分裂的value分配在push()功能,我添加了一個malloc()錯誤檢查。

備註如果您對此感到滿意,我會推薦使用Vlad的推送功能。它更短,更簡潔;但是,它犧牲了可讀性。因爲你是初學者,所以我決定將它分散開來可能更容易理解。