【问题标题】:Getting a segmentation fault error for stack in C在 C 中获取堆栈的分段错误错误
【发布时间】: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-&gt;size % MULTIPLIER == 0 绝不是堆栈已满的可靠指标。
  • @JohnBollinger 是的,我现在看到了,感谢您指出这一点。我这样做是为了如果元素的大小与数组的大小相同,则 isfull 函数将返回 1。

标签: arrays c pointers stack


【解决方案1】:

push() 重新分配时(它会在第一次推送时不必要地这样做),它不会使用指向重新分配空间的指针更新堆栈结构。假设原始指针在该点仍然有效是不安全的,因此以后尝试取消引用它是不安全的。这可能是造成段错误的缺陷。

另外,当push() 扩展堆栈存储时,它并没有遵循createstack() 的模型,为新元素分配空间来指向。这不是您在示例 main() 中看到的段错误的原因,但如果您推送了足够多的元素,这将是一个问题。

【讨论】:

  • 我没有意识到错误,感谢修复它!我还做到了s-&gt;stk 在 temp 重新分配后指向 temp。现在,要分配新元素,您认为在循环中运行for(unsigned int i = s-&gt;size; i &lt; (MULTIPLIER + s-&gt;arrsize); i++) 然后calloc'ing 每个元素就足够了吗?
  • 这看起来有道理,@AK,但这取决于您相对于 push() 执行的其他操作的位置。
猜你喜欢
  • 1970-01-01
  • 2011-10-30
  • 2023-03-12
  • 2013-10-05
  • 1970-01-01
  • 2012-05-21
  • 1970-01-01
  • 2013-04-18
相关资源
最近更新 更多