【发布时间】:2021-12-02 10:47:37
【问题描述】:
我有一个堆栈结构,它有一个 char 的动态双指针数组,它执行简单的堆栈操作。我用 calloc 初始化内存以在数组中具有确定的值。在数组大小达到 10 个元素后重新分配空间。
我的代码的堆栈结构:
typedef struct Stack{
unsigned int size; //The current number of elements in the stack
char **stk; //The actual stack represented by an array of strings
unsigned int arrsize; //To track the size of the array; gets incremented by 10 after limit
}stack;
我的堆栈文件的代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "stack.h"
#define MULTIPLIER 10
#define MAX_STR 1024
stack *createstack(void){
stack *s = malloc(sizeof(stack));
if(s == NULL){
perror("Failed to malloc!\n");
return NULL;
}
s->size = 0;
s->arrsize = MULTIPLIER;
s->stk = calloc(MULTIPLIER, sizeof(char*));
for (int i = 0; i < MULTIPLIER; i++){
s->stk[i] = calloc(MAX_STR, sizeof(char));
}
return s;
}
int isfull(const stack *s){
if(s->size % MULTIPLIER == 0){
return 0;
}
else{
return 1;
}
}
int isempty(const stack *s){
if(s->size == 0){
return 0;
}
else{
return 1;
}
}
void push(stack *s, char *item){
if(isfull(s) == 0){
char **temp = realloc(s->stk, (sizeof(char*)) * (MULTIPLIER + s->arrsize));
s->arrsize += MULTIPLIER;
if(temp == NULL){
perror("Realloc failed!");
}
}
strcpy((s->stk)[s->size], item);
s->size += 1;
}
char *pop(stack *s){
if(isempty(s) == 0){
printf("Stack is empty!");
return NULL;
}
else{
char *tmp = (char*) malloc(strlen((s->stk)[s->size-1]));
strcpy(tmp, (s->stk)[s->size-1]);
s->size -= 1;
return tmp;
}
}
void destroy(stack *s){
if(isempty(s) == 0){
printf("Stack is already empty!");
}
else{
for(size_t i=0; i < sizeof s; i++){
free((s->stk)[i]);
}
s->size = 0;
free(s->stk);
free(s);
}
}
现在,当我在主函数中做类似的事情时
int main(){
stack *stek = NULL;
stek = createstack();
push(stek, "first");
push(stek, "second");
push(stek, "third");
我收到 gcc 的“分段错误(核心转储)”错误。在检查 gdb 后,我确认它是由 push() 中的“strcpy”调用引起的。经过进一步的猜测,我得到的想法是,即使我使用 calloc 对其进行初始化,内存也可能没有分配给 s->stk 数组。任何有关如何解决此错误的帮助将不胜感激。
编辑:修正了在 cmets 中指出后代码中的一些小错误。
【问题讨论】:
-
sizeof(s)是指针的大小。sizeof(*s)或sizeof(stack)是结构的大小。 -
检查
if (s == NULL)需要在malloc之后立即进行。照原样,当malloc失败时,代码将在到达NULL检查之前发生段错误。 -
@user3386109 明白了,在我的程序里改了,谢谢
-
isfull()和isempty()函数的返回值是非常规的。 C 条件句使用 0 表示假,非零表示真,但您似乎采用了相反的约定。此外,即使考虑到这一点,您的isfull()功能也严重损坏。s->size % MULTIPLIER == 0绝不是堆栈已满的可靠指标。 -
@JohnBollinger 是的,我现在看到了,感谢您指出这一点。我这样做是为了如果元素的大小与数组的大小相同,则 isfull 函数将返回 1。