0

我是 C 语言的初学者。我正在尝试在输入通过时动态重新分配内存的任务(尽管对于这个测试我正在做一个正常的任务,稍后会尝试扩大它)。我面临的问题是我在写入内存时无法访问内存。谁能帮我理解这段代码哪里出错了。提前致谢。

代码:

#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;
} ```
4

1 回答 1

1

您缺少指针的初始化和其他一些问题...

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));

在 C 中,您不应该转换malloc. 在最好的情况下它是无用的。在最坏的情况下,它隐藏了真正的问题。

    /// 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;

这是您的分段错误的原因:您没有为第一个元素保留任何内存ab除了第一个元素test[0]。所有其他数组元素test[i]不包含任何有用的数据。取消引用这些指针是未定义的行为。

扩大数组后,您必须为每个字段分配内存。


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

你永远不应该将返回值realloc赋给你传递给函数的同一个变量。如果发生错误,您将获得NULL返回值,然后您的初始指针将丢失。

也在这里:不要投realloc

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

此处相同:不要分配给相同的变量,也不要强制转换realloc.

最后:这是缺少的部分:

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

当然,您应该检查所有返回值的错误结果。

与分段错误无关,但仍然值得修复:在使用最后一个元素后增加每个数组的大小。这为在循环的下一次迭代中填充新元素做好了准备。但是在最后一次迭代的情况下,它为内部指针ab外部数组分配了一个未使用的元素test

您将有一些未使用的元素:

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

改进的解决方案可能如下所示(未经测试)

我从每个指针开始,NULL并在使用realloc新元素之前使用它来避免额外的元素。

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;
}
于 2020-08-24T17:57:12.040 回答