结构表(C语言中的realloc)

qzlgjiam  于 2022-12-02  发布在  其他
关注(0)|答案(2)|浏览(170)

我正在尝试用C写一个代码,但是我在realloc上遇到了一些问题。我不得不写一个代码,它将创建一个堆栈,并将添加到它(dodaj_do_stosu),从它移除(usun_ze_stosu),并将查看该堆栈上的顶部内容。我在编译时遇到了问题(它确实对前两个单词有效,但随后返回(0xC0000374))。
我想我用错了realloc和我的结构的大小。如果有人能看看我的代码(特别是函数(dodaj_do_stosu)),告诉我我做错了什么thx。我的代码看起来像这样:

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

typedef struct {
    int n;
    char *nazwa;
}element_t;

typedef struct {
    int rozmiar;
    element_t **tablica;
}stos_t;

void top_of_stack(stos_t *s){
    printf("ostatni element stosu:rozmiar = %d nazwa=%s, n=%d\n", s->rozmiar,                         s->tablica[s->rozmiar]->nazwa, s->tablica[s->rozmiar]->n);
}
void init(stos_t *s)
{
    s->rozmiar=0;
    s->tablica=malloc(0);
}

void dodaj_do_stosu(stos_t *s, int n, char *name)
{

    s->tablica = realloc(s->tablica, (s->rozmiar + 1) * sizeof(s->tablica));
    s->tablica[s->rozmiar]->nazwa = name;
    s->tablica[s->rozmiar]->n = n;
    printf("rozmiar=%d, n=%d , nazwa=%s\n",s->rozmiar, s->tablica[s->rozmiar]->n, s->tablica[s->rozmiar]->nazwa);
    s->rozmiar++;

}

void usun_ze_stosu(stos_t *s)
{
    s->tablica = realloc(s->tablica, (s->rozmiar - 1) * sizeof(s->tablica[0]));
    s->rozmiar--;
}

void rm(stos_t s)
{
    free(s.tablica);
}

int main(int argc, char **argv)
{
    stos_t s;
    init(&s);
    int i;
    srand(time(0));
    if (argc>1)
        for(i=1;i<argc;i++){
            printf("%s\n", argv[i]);
            dodaj_do_stosu(&s, rand() % 10, argv[i]);
        }
    for(i=0;i<argc-1;i++){
        //printf("i=%d, n=%d, nazwa=%s\n",i, s.tablica[i].n, s.tablica[i].nazwa);
    }

    //top_of_stack(&s);
    //usun_ze_stosu(&s);
    //top_of_stack(&s);
    rm(s);
    return 0;

}
mtb9vblg

mtb9vblg1#

问题的一个重要方面是tablica是一个 pointers 数组,但您从未初始化指针本身。
dodaj_do_stosu函数重新分配数组,但不创建element_t对象。因此,任何对s->tablica[s->rozmiar]的解引用都将导致 undefined behavior
有两种可能的解决方案:
1.分配新的element_t结构:

s->tablica[s->rozmiar] = malloc(sizeof(element_t));

在初始化element_t结构成员之前。
1.使tablica成为结构 * 对象 * 的数组,而不是指针:

element_t *tablica;  // tablica is an array of objects, not an array of pointers

我推荐解决方案2。

ecbunoof

ecbunoof2#

至少函数dodaj_do_stosu是错误的。数据成员tablica声明如下

element_t **tablica;

因此,表达式s->tablica[s->rozmiar]具有类型element_t *和一个不确定的值。

s->tablica[s->rozmiar]->nazwa

调用未定义的行为。
必须为element_t结构类型的对象分配内存,而不是为element_t *类型的指针分配内存。
因此,您需要声明数据成员,如下所示

element_t *tablica;

并在函数中写入

s->tablica = realloc(s->tablica, (s->rozmiar + 1) * sizeof( *s->tablica));

此外,对于realloc的调用,使用中间指针更为安全。
该函数可以如下所示

int dodaj_do_stosu( stos_t *s, int n, char *name )
{
    element_t *tmp = realloc( s->tablica, ( s->rozmiar + 1 ) * sizeof( *s->tablica ) );
    int success = tmp != NULL;

    if ( success )
    {
        s->tablica = tmp; 
        s->tablica[s->rozmiar]->nazwa = name;
        s->tablica[s->rozmiar]->n = n;
        printf("rozmiar=%d, n=%d , nazwa=%s\n", s->rozmiar, s->tablica[s->rozmiar]->n, s->tablica[s->rozmiar]->nazwa );
        ++s->rozmiar;
    }

    return success;
}

因此,函数至少应该按照以下方式重新定义。例如,当s->rozmiar等于0时,它可以调用未定义的行为。

int usun_ze_stosu( stos_t *s )
{
    int success = s->rozmiar != 0;

    if ( success )
    {
        element_t *tmp = realloc( s->tablica, ( s->rozmiar - 1 ) * sizeof( *s->tablica ) );
        success = tmp != NULL;

        if ( success )
        {
            s->tablica = tmp;
            --s->rozmiar;
        }
    }

    return success;
}

同样在函数init中,如果编写

void init(stos_t *s)
{
    s->rozmiar=0;
    s->tablica = NULL;
}

另一个问题是函数rm

void rm(stos_t s)
{
    free(s.tablica);
}

你应该通过一个指针把原始对象传递给它,并在函数内写

void rm(stos_t *s)
{
    free( s->tablica );
    s->tablica = NULL;
    s->rozmiar = 0;
}

相关问题