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
相关产品推荐
相关产品推荐

