简体   繁体   中英

Initialize a stack in C by setting pointer to NULL

I'm trying to implement stack in C according to the following header (stack.h):

#ifndef STACK_H
#define STACK_H

/* An element from which stack is consisting */
typedef struct stack_node_ss {
  struct stack_node_ss *next;    /* pointer to next element in stack */
  void *value;                  /* value of this element */
} stack_node_s;

/* typedef so that stack user doesn't have to worry about the actual type of
 * parameter stack when using this stack implementation.
 */
typedef stack_node_s* stack_s;

/* Initializes a stack pointed by parameter stack. User calls this after he
 * has created a stack_t variable but before he uses the stack.
 */
void stack_init(stack_s *stack);

/* Pushes item to a stack pointed by parameter stack. Returns 0 if succesful,
 * -1 otherwise.
*/
int stack_push(void *p, stack_s *stack);

/* Pops item from a stack pointed by parameter stack. Returns pointer to
 * element removed from stack if succesful, null if there is an error or
 * the stack is empty.
 */
void *stack_pop(stack_s *stack);

#endif

However, being new with C, I'm stuck at the stack_init function, I have written in stack.c:

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

void stack_init(stack_s *stack) {
    (*stack)->value = NULL;
    (*stack)->next = NULL;
}

The main program begins with:

  int *tmp;
  stack_s stack;
  stack_init(&stack);

And this crashes my program with:

Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x0000000000000008
0x0000000100000abf in stack_init (stack=0x7fff5fbffb30) at stack.c:6
6       (*stack)->value = NULL;

Can you hint me to the right track? Many thanks.

You have to allocate memory for **stack itself:

*stack = malloc(sizeof(**stack));

But please don't typedef pointer types. That's really confusing and hard to read. Better to pass the pointer by value and leave it to the caller to store the pointer, like this:

typedef struct stack_node_t
{
    struct stack_node_t * next;
    /* ... */
} stack_node;

stack_node * create_stack()
{
    stack_node * res = calloc(1, sizeof(stack_node));
    return res;
}

void destroy_stack(stack_node * s)
{
    if (!next) return;

    stack_node * next = s->next;
    free(s);
    destroy_stack(next);
}

// etc.

Then you can just say:

stack_node * s = create_stack();

// use s

destroy_stack(s);
s = NULL;  // some people like this

You are dereferencing an uninitialised pointer, causing undefined behaviour.

Because this function is creating a new stack, you need to allocate some dynamic memory for the stack and then set the pointer to point to that newly allocated memory:

void stack_init(stack_s *stack) {
    *stack = malloc(sizeof(**stack)); // create memory for the stack

    (*stack)->value = NULL;
    (*stack)->next = NULL;
}

stack_s stack;
stack_init(&stack);

Then you should have a function called stack_destroy that will free the dynamic memory and set the pointer to NULL :

void stack_destroy(stack_s *stack) {
    free(*stack);
    *stack = NULL;
}

You should initialize the stack to NULL - not to push a NULL value to it:

void stack_init(stack_s *stack) {
    *stack=NULL;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM