realloc():realloc无效的下一个大小和malloc():malloc内存损坏很快

时间:2017-06-23 12:53:12

标签: c malloc realloc

我正在创建堆栈

typedef struct cool {
     int value; 
}arr;

typedef struct stack {
     int top;
     arr **st;
}STACK;

我需要通过一次增加一个块来创建STACK dynamicall。所以我尝试了这样..

int size = 1;
STACK *mainstack;

mainstack = (STACK *) malloc (sizeof(STACK));
create(mainstack);
create(mainstack);
create(mainstack);

void create(STACK *mainstack) {
       if((mainstack = realloc(mainstack, (size + 1))) != NULL) {
               mainstack[size].st = (arr **) malloc(10 * sizeof(arr*));
        }
        ++size;
}

我第一次调用create()没有问题..但是我再次通过调用create()重新分配我得到这样的错误... realloc():下一个大小无效.....

所以我改变了

的realloc
mainstack = realloc(mainstack, (size + 1) * sizeof(STACK));

然后我再次得到这样的错误..

malloc():内存损坏很快

两次我叫做创造它的工作好。但是aftrer第三次调用显示错误.. 请有人告诉我这些背后究竟是什么?或者没有任何其他方法来实现我的想法而不会出现这些错误..

2 个答案:

答案 0 :(得分:1)

这不起作用:

void create(STACK *mainstack){
  if ((mainstack = realloc(mainstack, (size + 1))) != NULL) {
    mainstack[size].st = (arr **)malloc(10 * sizeof(arr*));
  }
  ++size;
}

mainstack = realloc(mainstack...修改本地变量mainstack,该变量将超出函数末尾的范围。

因此,在create(mainstack);之后,mainstack将保持不变。

简单示例:

void foo(int bar)
{
  bar = 2;
}
...

int x = 123;
foo(x);
// x contains 123 and n ot 2

例如,你需要这个:

STACK *create(STACK *mainstack){
  if ((mainstack = realloc(mainstack, (size + 1))) != NULL) {
    mainstack[size].st = (arr **)malloc(10 * sizeof(arr*));
  }
  ++size;

  return mainstack;
}

int main()
{
  int size = 1;
  STACK *mainstack;

  mainstack = malloc(sizeof(STACK));
  mainstack = create(mainstack);
  mainstack = create(mainstack);
  mainstack = create(mainstack);
}

也就是说,使用全局变量size的整体设计不是很好,create中的错误处理很糟糕。

答案 1 :(得分:1)

因此,您希望创建一个动态增长的堆栈,并且您已经有一个答案可以解释您的代码出错的地方。设计似乎有点复杂,因此我会向您展示一些解决方案的注释代码,我只考虑直接,只使用一个struct

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

typedef struct Stack
{
    size_t capacity;  // how many items the stack can hold right now
    size_t index;     // index of the first unused element
                      // (kind of a "stack pointer")
    int stack[];      // the elements, variable length
} Stack;

Stack *Stack_create(size_t n)
{
    // create stack with room for `n` elements
    Stack *self = malloc(sizeof(Stack) + n * sizeof(int));
    // you need to add `n * sizeof(int)` here for the flexible array member

    if (!self) exit(1);
    self->capacity = n;
    self->index = 0;
    return self;
}

void Stack_destroy(Stack *self)
{
    if (!self) return;
    free(self);
}

void Stack_push(Stack **self, int val)
{
    Stack *s = *self;
    if (s->index == s->capacity)
    {
        // if necessary, double the number of elements the stack can hold
        s->capacity *= 2;
        s = realloc(s, sizeof(Stack) + s->capacity * sizeof(int));
        if (!s) exit(1);
        *self = s;
    }
    s->stack[s->index++] = val;
}

int Stack_pop(Stack *self, int *val)
{
    if (self->index)
    {
        *val = self->stack[--self->index];
        return 1;
    }
    else
    {
        return 0;
    }
}

int main(void)
{
    Stack *stack = Stack_create(5);

    Stack_push(&stack, 47);
    Stack_push(&stack, 12);
    Stack_push(&stack, 73);
    Stack_push(&stack, 5);
    Stack_push(&stack, 13);
    Stack_push(&stack, 23);

    int val;
    while (Stack_pop(stack, &val))
    {
        printf("%d ", val);
    }
    putchar('\n');

    Stack_destroy(stack);

    return 0;
}

关于此的说明:

  • 为了简洁起见,malloc()realloc()上的错误检查很少。在实践中,当然没有什么可以做的,也许exit(1)就足够了,但是如果你的程序更复杂,你可能想要向调用者返回一个错误,所以它可以例如fflush()个文件等。

  • 您通常希望避免realloc()次呼叫的批次(它们可能很昂贵)。如果需要更多空间,则提前分配一些空间并将空间加倍是这种数据结构的常用方法。

  • 如果您不想将双指针传递给Stack_push(),您必须使用指针代替灵活数组成员,如下所示:

    typedef struct Stack
    {
        size_t capacity;
        size_t index;
        int *stack;
    } Stack;
    

    然后,您必须通过单独调用malloc()为此分配空间,并且只需要此成员上的realloc