首页 > 解决方案 > 函数中的结构数组重新分配 - 产生未定义的行为

问题描述

我有一个包含 3 个字符指针(任意长度字符串)的结构,并且我使用 malloc 创建了一个动态数组,因为它可以有任意数量的条目。这是我的结构数据类型:

typedef struct student{
    char* name;
    char* phoneNumber;
    char* department;
}STUDENT;

每当需要新条目时,我使用了一个函数来重新分配来增加结构数组的大小,并使用另一个函数来打印整个数组。

我遇到的问题是:我能够在 addNumber 函数中打印新条目,但是当我尝试在 addNumber 函数之外打印时,情况并非总是如此。有时它可以工作,大多数时候我遇到分段错误:11 和一次在添加新条目时我得到一个'malloc:对象 0x7fc426c058f0 的 *** 错误:未分配重新分配的指针'

这是我的主要内容:

int nEntry = 0;
STUDENT* directory = malloc(nEntry * sizeof *directory);
if(directory == NULL){
    puts("Unable to allocate memory");
    exit(-1);
}
while(1){
    int choice = 0;
    scanf("%d", &choice);
    while(getchar() != '\n');
    switch(choice){
        case 1:
            printDirectory(directory, nEntry);
            break;
        case 2:
            addNumber(directory, &nEntry);
            break;
        default:
            printf("Unknown option!\n");
            break;
    }
}
return 0;

这是我的 addNumber 函数:

void addNumber(STUDENT* Array, int* nArray){
    *nArray += 1;
    int x = *nArray - 1;
    STUDENT* tempDirectory = realloc(Array, *nArray * sizeof *Array);
    if(tempDirectory == NULL){
        puts("Unable to allocate memory");
        exit(-1);
    }
    else{
        Array = tempDirectory;
        Array[x].name = (char*)malloc(sizeof(char*));
        Array[x].phoneNumber = (char*)malloc(sizeof(char*));
        Array[x].department = (char*)malloc(sizeof(char*));

        printf("Name: ");
        scanf("%[^\n]", Array[x].name);
        while(getchar() != '\n');

        printf("Number: ");
        scanf("%[^\n]", Array[x].phoneNumber);
        while(getchar() != '\n');

        printf("Department: ");
        scanf("%[^\n]", Array[x].department);
        while(getchar() != '\n');

        for(int i = 0; i < *nArray; i++){
        printf("%s\t%s\t(%s)\n", (Array + i)->name, (Array + i)->phoneNumber, (Array + i)->department);
        }
    }
}

这是我的打印功能:

void printDirectory(STUDENT* Array, int nArray){
    int i;
    for(i = 0; i < nArray; i++){
        printf("%s\t%s\t(%s)\n", (Array + i)->name, (Array + i)->phoneNumber, (Array + i)->department);
    }
}

如果我将条目硬编码到 main 中,打印功能可以正常工作,问题似乎是在 addNumber 函数中创建的内容没有正确传回?但是对于我通过引用传递的所有论点,我很困惑为什么我会得到一个未定义的行为。

标签: cstructdynamic-memory-allocationc-strings

解决方案


正如评论中所指出的,您malloc的 s 大小错误,因此您的代码还有其他问题,但要解决您对 realloc 的具体担忧:

要存储 的返回值realloc以便可以在主函数中访问它,您需要传递指针的地址。

所以主要是:

addNumber(&directory, &nEntry); // Note the ampersand

在 addNumber 中:

void addNumber(STUDENT** Array, int* nArray){ // Note the pointer to a pointer
...
STUDENT* tempDirectory = realloc(*Array, *nArray * sizeof *Array); // Note Array is dereferenced
...
*Array = tempDirectory;
...

如果您将directorymain 中的变量描述为存储在位置 0x1 并指向内存位置 0x2 的变量,那么在您当前的代码中,您将向函数发送 0x2。该函数可以在那里读取数据,但它没有引用 0x1 来更新directorymain 中的变量。

通过引用传递的一般规则是:如果要更新函数中的引用以便调用者可以读取它,则需要在传递它时使用比调用者中的变量多一个星号。所以如果你有一个intin main,你会想要更新int*函数中的一个。如果你有一个int***in main,你会想要更新一个int****.


推荐阅读