动态分配内存的问题(C)

3lxsmp7m  于 2023-04-05  发布在  其他
关注(0)|答案(1)|浏览(188)

我正在学习数据结构。所以我决定自己用数组实现一个栈。问题是当程序试图在栈满的时候推送一个元素。我的想法是realloc()指向数组的现有指针,我以前用malloc手动分配内存()将堆栈的大小增加1,然后推送相应的Item。在valgrind上运行代码后,它向我显示错误:“大小为4的无效写入...在大小为16的块分配之前有4个字节“。注意到我是初学者,因此感谢任何帮助。

typedef struct {
    int *v;    
    int cap;    
    int sz;
} stack;

stack* build(){
    stack *new = (stack*) malloc(sizeof(stack));
    new->v = (int*) malloc(sizeof(int) * 4);
    new->cap = 4;
    new->sz = 0;
    return new;
}

int is_empty(stack *s){
    return s->sz == 0;
}

int push( stack *s, int e )
{
    int success = 1;

    if (s->sz == s->cap){
        int*tmp =(int*)realloc(s->v,(s->cap+1)*sizeof( int));
        if (( success = tmp != NULL )){
            s->v = tmp;
            ++s->cap;
        }
    }

    if (success){
        s->v[s->sz++] = e;
    }

    return success;
}
int top(stack *s){
    return *(s->v);
}

int pop(stack *s){
    int value;

    if(is_empty(s))
        return -1;

    value = *(s->v);
    s->v--;
    s->sz--;
    return value;   
}

void destroy(stack *s){
    s->v -= s->sz + 1;
    free(s->v);
    free(s);
}

int match(char p1, char p2){
    if(p1 == '(')
        return (p1 - p2) == '(' - ')';
    else if(p1 == '[')
        return (p1 - p2) == '[' - ']';
    else
        return (p1 - p2) == '{' - '}';
}

int main(){
    int c;
    stack *s = build();
    while((c = getchar()) != EOF && c != '\n'){
        if(c == '(' || c == '[' || c == '{')
             push(s, c);
        else if(c == ')' || c == ']' || c == '}'){
            if(!match(pop(s), c)){
                printf("no\n");
                destroy(s);
                return 0;
            }
        }
    }
    puts((is_empty(s)) ? "yes" : "no");
    destroy(s);
    return 0;
}
pinkon5k

pinkon5k1#

realloc的调用

s->v = (int*) realloc(s->v + 1 - s->sz, sizeof(int) * (s->cap + 1));

不正确。函数的第一个参数应该是指向先前分配的内存的原始指针或NULL。
此外,在函数push中进行此检查

if(is_empty(s))
    *(s->v) = e;

是多余的。
函数可以看起来像下面这样。注意函数不应该发出任何消息。它是函数的调用者,将根据新项是否成功添加来决定是否输出消息。

int push( stack *s, int e )
{
    int success = 1;

    if ( s->sz == s->cap )
    {
        int *tmp = realloc( s->v, ( s->cap + 1 ) * sizeof( int ) );

        if ( ( success = tmp != NULL ) )
        {
            s->v = tmp;
            ++s->cap;
        }
    }

    if ( success )
    {          
        s->v[s->sz++] = e;
    }

    return success;
}

下面是一个演示程序,展示了函数push的用法。

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

typedef struct {
    int *v;
    int cap;
    int sz;
} stack; 

/* In case this is how I innitialize an array: */
stack *build() {
    stack *new = ( stack * )malloc( sizeof( stack ) );
    new->v = ( int * )malloc( sizeof( int ) * 4 );
    new->cap = 4;
    new->sz = 0;
    return new;
}

int push( stack *s, int e )
{
    int success = 1;

    if (s->sz == s->cap)
    {
        int *tmp = ( int * )realloc( s->v, ( s->cap + 1 ) * sizeof( int ) );

        if (( success = tmp != NULL ))
        {
            s->v = tmp;
            ++s->cap;
        }
    }

    if (success)
    {
        s->v[s->sz++] = e;
    }

    return success;
}

int main( void )
{
    stack *s = build();

    for (int i = 0; i < 10; i++)
    {
        if (!push( s, i ))
        {
            puts( "Error: not enough memory." );
        }
    }

    for (int i = s->sz; i != 0; )
    {
        printf( "%d ", s->v[--i] );
    }
    putchar( '\n' );
}

程序输出为

9 8 7 6 5 4 3 2 1 0

当然,你需要自己写一个函数来释放所有分配的内存。
请注意,最好将堆栈定义为单链表。

相关问题