You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言动态栈push初始化后指针仍为NULL致段错误求助

动态栈push函数初始化后外部指针仍为NULL的问题

为学习目的编写了一个动态栈,期望push()函数能处理dstack未初始化的情况。用gdb调试时,push()内部流程正常,已经初始化了栈并返回指针,但从push()返回后,main函数中传入print_dstack()的指针依然是NULL,最终触发段错误。

相关代码

dstack.h

#pragma once
#ifndef _DSTACK_H_
#define _DSTACK_H_

enum stack_inits {
  DEFAULT_SIZE = 16,
  DEFAULT_SPACE = 32
};

typedef struct {
    int size;
    int length;
    int *stack;
} dstack_t;

static void *init(const int size);

static void resize(dstack_t *stack);

void *push(dstack_t *stack, int item);

void print_dstack(dstack_t const *stack);

void free_dstack(dstack_t *stack);

#endif

dstack.c

#include "dstack.h"
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>

static void *init(const int size)
{
  dstack_t *stack;
  if( (stack = (dstack_t*)malloc(sizeof(dstack_t))) == NULL)
    return NULL;
  if( (stack->stack = (int*)malloc(size * sizeof(int))) == NULL) {
    free(stack->stack);
    free(stack);
    return NULL;
  }
  stack->size = size;
  stack->length = 0;

  return stack;
}

static void resize(dstack_t *stack)
{
  stack->size += DEFAULT_SPACE;
  int *newStack = realloc(stack->stack, sizeof(int) * stack->size);
  assert(newStack);
  stack->stack = newStack;
}

void *push(dstack_t *stack, int item)
{
  if(stack == NULL)
    stack = init(DEFAULT_SIZE);
  if(stack->stack == NULL)
    if( (stack->stack = (int*)malloc(DEFAULT_SIZE * sizeof(int))) == NULL) {
      free(stack->stack);
      return NULL;
    }
  if(stack->length == stack->size)
    resize(stack);
  stack->stack[stack->length++] = item;
  return &stack->stack[stack->length-1];
}

void print_dstack(dstack_t const *stack)
{
  assert(stack);
  for(int i = 0; i < stack->length; i++)
  {
    if(i % 2 == 0)
      putchar('\0');
    printf("stack[%d] = %d\t", i, stack->stack[i]);
  }
}

void free_dstack(dstack_t *stack)
{
  free(stack->stack);
  free(stack);
}

stack_test.c

#include "dstack.h"
#include <stdio.h>

int main()
{
  dstack_t *stack = NULL;
  push(stack, 10);

  print_dstack(stack);
  free_dstack(stack);
  return 0;
}

问题根源

C语言的函数参数传递是传值调用,push()函数中的stack是形参,它是main中stack指针的一份拷贝。当push()里判断stack == NULL后,调用init()分配内存并赋值给形参stack,这只会修改形参的指向,不会影响main函数中原来的stack指针——它依然是NULL。这就是为什么调试时push()内部流程正常,但返回后外部指针没变化的原因。

解决方案

有两种常见的修复方式:

方式一:让push返回dstack_t*指针

修改push()的返回值类型为dstack_t*,并在main中接收返回的指针,更新原变量:

修改dstack.h中的push声明:

dstack_t *push(dstack_t *stack, int item);

修改dstack.c中的push实现:

dstack_t *push(dstack_t *stack, int item)
{
  if(stack == NULL)
    stack = init(DEFAULT_SIZE);
  if(stack->stack == NULL) {
    if( (stack->stack = (int*)malloc(DEFAULT_SIZE * sizeof(int))) == NULL) {
      free(stack);
      return NULL;
    }
  }
  if(stack->length == stack->size)
    resize(stack);
  stack->stack[stack->length++] = item;
  return stack;
}

修改main函数中的调用:

int main()
{
  dstack_t *stack = NULL;
  stack = push(stack, 10); // 接收返回的栈指针

  print_dstack(stack);
  free_dstack(stack);
  return 0;
}

方式二:使用指针的指针作为参数

通过传递指针的地址,让push()直接修改外部指针的指向:

修改dstack.h中的push声明:

void *push(dstack_t **stack, int item);

修改dstack.c中的push实现:

void *push(dstack_t **stack, int item)
{
  if(*stack == NULL)
    *stack = init(DEFAULT_SIZE);
  if((*stack)->stack == NULL) {
    if( ((*stack)->stack = (int*)malloc(DEFAULT_SIZE * sizeof(int))) == NULL) {
      free(*stack);
      *stack = NULL;
      return NULL;
    }
  }
  if((*stack)->length == (*stack)->size)
    resize(*stack);
  (*stack)->stack[(*stack)->length++] = item;
  return &(*stack)->stack[(*stack)->length-1];
}

修改main函数中的调用:

int main()
{
  dstack_t *stack = NULL;
  push(&stack, 10); // 传入指针的地址

  print_dstack(stack);
  free_dstack(stack);
  return 0;
}

另外注意原代码中的一个小问题:init()里如果malloc(stack->stack)失败,free(stack->stack)是不必要的,因为此时stack->stack还是NULL,free(NULL)是安全但多余的,可以直接删除这一行。

内容的提问来源于stack exchange,提问作者rat

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 12:47:17