简体   繁体   中英

How to dynamically increase size of any structure objects during runtime?

I am a bit of a beginner in C language. I was trying out a task of dynamically reallocating memory as the input comes through(although for this test I am doing a normal task, later will try to scale it up). the issue I am facing is I am unable to access the memory while writing into it. Can anyone please help me understand where I am going wrong in this code. thanks in advance.

code:

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

struct ai {
    int* a;
    char* b;
};

int main()
{
    struct ai *test;
    test = (struct ai*) malloc(sizeof(struct ai));
    test[0].a = (int*)malloc(sizeof(int));
    test[0].b = (char*)malloc(sizeof(char));

    /// storing info

    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            test[i].a[j] = j;
            test[i].b[j] = 65 + j;
            test[i].a = (int *) realloc(test[i].a, (j + 2) * sizeof(int));
            test[i].b = (char*) realloc(test[i].b, (j + 2) * sizeof(char));
        }
        test = (struct ai*)realloc(test, (i + 2) * sizeof(struct ai));
    }

    // printing the block out

    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            printf("%d , %c\n", test[i].a[j], test[i].b[j]);
        }
    }
    return 0;
} ```

You have missing initialization of your pointers and some other issues...

int main()
{
    struct ai *test;
    test = (struct ai*) malloc(sizeof(struct ai));
    test[0].a = (int*)malloc(sizeof(int));
    test[0].b = (char*)malloc(sizeof(char));

In C you should not cast the result of malloc . In best case it is useless. In worst case it hides real problems.

    /// storing info

    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            test[i].a[j] = j;
            test[i].b[j] = 65 + j;

Here comes the reason for your segmentation fault: You do not have any memory reserved for a and b except for the first element test[0] . All other array elements test[i] do not contain any useful data. Dereferencing these pointers is undefined behaviour.

You must allocate memory for each field after you enlarged your array.


            test[i].a = (int *) realloc(test[i].a, (j + 2) * sizeof(int));
            test[i].b = (char*) realloc(test[i].b, (j + 2) * sizeof(char));

You should never assign the return value of realloc to the same variable that you passed into the function. In case of an error you will get NULL return value and then your initiali pointer is lost.

Also here: don't cast for realloc as well.

        }
        test = (struct ai*)realloc(test, (i + 2) * sizeof(struct ai));

Same here: Don't assign to same variable and don't cast the result of realloc .

Finally: Here goes the missing part:

        test[i+1].a = malloc(sizeof(*test[0].a));
        test[i+1].b = malloc(sizeof(*test[0].b));
    }

Of course you should check all return values for error results.

Not related to the segmentation fault, but still worth to fix: You increment the size of each array after you used the last element. This prepares the new element for being filled in next iteration of the loops. But in case of the last iteration it allocated an unused element for both the intern pointers a and b as well as the outer array test .

You will have some unused elements:

test[0].a[4]
test[0].b[4]
test[1].a[4]
test[1].b[4]
test[2].a[0]
test[2].b[0]

An improved solution could look like this (not tested)

I start with each pointer being NULL and use realloc right before the new element is used to avoid the extra elements.

int main(void)
{
    struct ai *test = NULL
    void *tmp;

    // storing info
    for (int i = 0; i < 2; i++)
    {
        tmp = realloc(test, (i+1) * sizeof(*test))
        if (tmp == NULL)
            exit(1);

        test = tmp;
        test[i].a = NULL;
        test[i].b = NULL;

        for (int j = 0; j < 4; j++)
        {
            tmp = realloc(test[i].a, (j+1) * sizeof(test[i].a[0]));
            if (tmp == NULL)
                exit(1);
            test[i].a = tmp;

            tmp = realloc(test[i].b, (j+1) * sizeof(test[i].b[0]));
            if (tmp == NULL)
                exit(1);
            test[i].b = tmp;

            test[i].a[j] = j;
            test[i].b[j] = 65 + j;
        }
    }

    // printing the block out
    for (int i = 0; i < 2; i++)
    {
        for (int j = 0; j < 4; j++)
        {
            printf("%d , %c\n", test[i].a[j], test[i].b[j]);
        }
    }
    return 0;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM