2015-03-31 64 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的推送功能。它更短,更简洁;但是,它牺牲了可读性。因为你是初学者,所以我决定将它分散开来可能更容易理解。