C - 结构分段错误

C - Segmentation fault with struct

如果这是一个简单的问题,我真的很抱歉,但我是初学者。 我有一项任务是将一些函数写入堆栈结构。给出了结构。我无法摆脱 push() 行中的分段错误 "s->elements..." 经过几个小时的谷歌搜索和搜索后,我不知道出了什么问题。

代码如下:

#define STACK_SIZE 5</p>

#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;
}

因为你是按值传递两个指针(所以你实际上传递的是指针的副本),将初始化函数更改为 int initilize(stack **s) 并将 s = newStack; 更改为 *s = newStack;然后像这样调用初始化 initialize(&sA); initialize(&sB);

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

当您将指针传递给函数时,函数会接收到指针的副本。这通常没问题,除非你是 changing/creating 指针的起始地址

在您的例子中,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;
}

我认为您需要如下内容

#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;
}

您收到分段错误,因为您正试图将 push() 中的值分配给未分配的内存区域。 initialize() 可以成功分配内存并使用 count = 0 对其进行初始化,但是您对 s = newStack 的分配不起作用。正如 David 和 Alejandro 指出的那样,你传递的是 "a copy of the pointer." 本质上,你传递的是未初始化的 stack 变量的地址,但你没有传递给函数一种用新地址更新该变量的方法.您需要向它传递一个指向堆栈指针的指针。 (也称为二级指针。)这意味着 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;
}

我还稍微修改了代码,在 push() 函数中拆分了 value 的赋值,并添加了 malloc() 错误检查。

注意: 如果您觉得方便的话,我推荐使用Vlad的推送功能。它更短更简洁;但是,它牺牲了可读性。由于您是初学者,我决定将其展开可能更容易理解。