C-带结构的分段错误

C-带结构的分段错误,c,struct,segmentation-fault,stack,C,Struct,Segmentation Fault,Stack,如果这是一个容易解决的问题,我真的很抱歉,但我是一个初学者。 我有一个任务将一些函数写入堆栈结构。给出了结构。我无法消除push()行的->元素中的分段错误 我不知道在几个小时的谷歌搜索之后,到底出了什么问题 代码如下: #define STACK_SIZE 5 #include <stdio.h> #include <stdlib.h> typedef struct stackADT { int elements[STACK_SIZE]; int c

如果这是一个容易解决的问题,我真的很抱歉,但我是一个初学者。 我有一个任务将一些函数写入堆栈结构。给出了结构。我无法消除push()行的->元素中的分段错误 我不知道在几个小时的谷歌搜索之后,到底出了什么问题

代码如下:
#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; }
#定义堆栈大小5

#包括 #包括 类型定义结构stackADT{ int元素[堆栈大小]; 整数计数; }堆叠; 无效初始化(堆栈*s) { 堆栈*新闻标题; newStack=malloc(sizeof(*newStack)); 新闻标题->计数=0; s=新闻标题; } int push(堆栈*s,int值) { 如果(s->count==5)返回-1; 否则{ s->elements[s->count++]=值; 返回s->elements[s->count-1]; } } int main() { 堆栈*sA; stack*sB; 初始化(sA); (某人); printf(“%d\n”,push(sA,3)); 返回0; }
因为您是按值传递两个指针(因此实际上是传递指针的副本),所以将initialize函数更改为
int initilize(stack**s)
s=newStack
*s=newStack然后像这样调用initialize
initialize(&sA);初始化(&sB)


你真的不应该动态分配对象,除非你必须这样做,而且你没有
空闲()
占用你分配的内存,这是内存泄漏。

当你将指针传递给函数时,函数会收到指针的副本。这通常很好,除非您正在更改/创建指针的起始地址

在您的情况下,
sA
sB
不包含地址(当您将它们传递到
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;
}

我想你需要像下面这样的东西

#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;
}
#包括
#定义堆栈大小5
类型定义结构stackADT
{
int元素[堆栈大小];
整数计数;
}堆叠;
无效初始化(堆栈*s)
{
s->count=0;
}
int push(堆栈*s,int值)
{
返回s->count==堆栈大小?-1:(s->elements[s->count++]=value);
}
内部主(空)
{
堆栈sA;
堆叠某人;
初始化(&sA);
初始化(&sB);
printf(“%d\n”,推送(&sA,3));
返回0;
}

您收到分段错误,因为您试图在
push()
中为未分配的内存区域分配一个值
initialize()
可以成功地分配内存并使用
count=0
对其进行初始化,但是
s=newStack
的分配不起作用。正如David和Alejandro所指出的,您传递的是“指针的副本”。本质上,您传递的是未初始化的
堆栈
变量的地址,但您并没有传递函数一种用新地址更新该变量的方法。您需要向它传递一个指向堆栈指针的指针。(也称为二级指针。)这意味着
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;
}
#定义堆栈大小5
#包括
#包括
类型定义结构stackADT{
int元素[堆栈大小];
整数计数;
}堆叠;
无效初始化(堆栈**s)
{
堆栈*新闻标题;
newStack=malloc(sizeof(*newStack));
if(NULL==newStack){
//Malloc无法分配内存
//用于新闻标题。
//将s设置为NULL以指示错误
s=零;
//过早返回
返回;
}//否则,malloc成功了
新闻标题->计数=0;
//将malloced堆栈指针的值分配给堆栈**s的指针对象
*s=新闻标题;
}
int push(堆栈*s,int值)
{
如果(s->count==堆栈大小){
//堆栈中的元素太多。
//返回错误值(-1)
返回-1;
}否则{
//将新值指定给当前的最后一个索引
s->elements[s->count]=值;
//添加计数以指示已添加新变量
s->count++;
//使用数组返回刚刚添加的值
返回s->elements[(s->count-1)];
}
}
int main()
{
堆栈*sA;
stack*sB;
//向函数发送指向堆栈指针的指针
初始化(&sA);
初始化(&sB);
if(sA==NULL){
puts(“无法为堆栈变量sA分配内存。\n”);
返回-1;
}
printf(“%d\n”,push(sA,3));
//清理记忆
免费(sA);
自由(某人);
返回0;
}
我还稍微修改了代码,在
push()
函数中拆分了
value
的赋值,并添加了
malloc()
错误检查


注意:如果您对它感到满意,我建议您使用Vlad的推送功能。它更短更简洁;然而,它牺牲了可读性。由于您是初学者,我决定将其展开可能更容易理解。

@Mirko Richter为什么要动态分配stack类型的对象?您可以简单地定义一个堆栈,如stacksa;函数初始化也不初始化任何内容。:)OK。如何将函数initialize更改为初始化某些内容?;)谢谢,这个有用!我得到的部分是指针的副本。在里面