最后一次循环迭代时的内存分配失败

时间:2014-11-20 17:24:52

标签: c arrays memory-management struct

所以...过去我被告知我的问题并不好......我相信这主要是因为我还没有把问题代码隔离得太好。我会尽力在这篇文章中提出一个尖锐,简洁,重要的问题。我当然愿意接受有关如何更好地提出问题的建议。 谢谢。

我正在研究C中的一个小项目,该项目将作为我已经工作了一段时间的大型错误项目的原型。我试图先在一个较小的程序中解决细节问题。我有两个结构:

struct list
{
    char ownerName[20];
    int ownerAge;
    char sex;
}owner;

struct list2
{
    char petName[20];
    char owner[20];
    char animal[4];
    char breed[50];
    char color[20];
}pets;

该程序应该从用户输入fgets ownerName并将其与" .owner"在宠物结构中。然后应将ownerName和petName元素复制到一个数组中,并将所有者和他/她的宠物的名称打印在一个列表中。虽然我知道我不需要所有者结构来实现这一点,但我使用它来模拟我正在编写的其他程序。

我正在使用

if (strcmp(pets[i].owner, name) == 0) 

比较结构元素,似乎有这个部分。

变量j计算满足此条件的记录数,变量l = j + 1.我使用以下方法调用数组:

char *petsList[l];

数组的大小由l(j + 1)决定,因为我需要为所有者名称的petNames + 1元素使用j个元素。

我还通过以下方式创建了一个指向petsList数组的指针:

char *(*ptr)[l] = &petsList

通过以下命令将所有者名称添加到数组中:

(*ptr)[0] = (char *)malloc(sizeof(name));
strcpy ( (*ptr)[0], name);

使用for循环将petNames添加到数组petsList中。我已初始化i = 1以防止petsList [0]被覆盖,并试图通过以下循环将petNames写入数组:

 i = 1;

        for (k=0; k < PETS; k++)
        {
            if (strcmp(pets[k].owner, name) == 0)
            {
                (*ptr)[i] = (char *)malloc(sizeof(pets[k].petName));
                if (!*(ptr)[i])
                {
                    puts("\nMemory Allocation Error");
                    exit (1);
                }
                strcpy( (*ptr)[i], pets[k].petName);
                i++;
             }
         }

让我们说一下给定的名字输入,我得到三只匹配的宠物。循环迭代前两次就好了,但是在循环的第三次迭代中,我得到了内存分配错误。这发生在循环的最后一次迭代中。例如,如果我有2个与ownerName关联的宠物,则列表将运行第一次迭代并且在第二次迭代时失败;如果我有4个与ownerName关联的宠物,循环将在前3次运行正常并在第4次失败,因此看起来循环的最终迭代始终失败。我曾尝试多次更改代码,但现在我不知道如何继续使用这个程序。任何帮助是极大的赞赏。

感谢。

2 个答案:

答案 0 :(得分:0)

这有点奇怪。也许:

if(!*(ptr)[i])

应该是

if(!(*ptr)[i])

答案 1 :(得分:0)

不要施放malloc返回值。

因为我不能用最小的例子来检查。

char *(*ptr)[l] = &petsList

为什么要制作如此复杂的构造?我甚至不确定它应该完成什么。你想让第一个索引和下一个索引中的所有宠物都包含所有者吗?这可以通过petslist

完成

最后你真正需要什么结构?

是这样的:

数组:

0 = owner
1 = pet 1
2 = pet 2

或类似

0,0 = owner       1,0 = owner 2        etc.
0,1 = pet 1       1,1 = pet 3
0,2 = pet 2       1,2 = pet 4

好的,这是一个你想做的工作实例。您可以轻松扩展它以执行第二种数据安排。如果您有任何问题,请随时提出

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

#define PETAMOUNT   40

struct list2
{
    char petName[20];
    char owner[20];
    char animal[4];
    char breed[50];
    char color[20];
};

int main() {
    struct list2 *pets;             // list of all pets
    char name[128];                 // contain name of the owner, get from stdin

    unsigned int i;                 // i and j are both counter variable
    unsigned int j;

    fgets(name, 128, stdin);        // get string from stdin
    name[strlen(name) - 1] = '\0';  // remove newline

    pets = malloc(PETAMOUNT * sizeof(struct list2));    // allocate memory for the list of all pets
    if (pets == NULL) {
        printf("malloc err\n");
        exit(1);
    }

    for (i = 0; i < PETAMOUNT; i++) {           // initialize some pets and some owners
        strcpy(pets[i].petName, "petname ");
        strcpy(pets[i].owner, "owner ");
        pets[i].petName[7] = i + '0';           // there are PETAMOUNT of petnames. petname0, petname1 etc
        pets[i].owner[5] = (i / 4) + '0';       // there are PETAMOUNT / 4 owners. owner0 has petname0 to petname3, owner1 has petname4 to 7 etc
    }


    char ***petslist;                       // a list of list of strings or 3d char array
    petslist = malloc(sizeof(char **));     // allocate pointer to contain a double array
    petslist[0] = malloc(sizeof(char *));   // allocate a pointer to contain the name of the owner
    if (petslist[0] == NULL) {
        printf("malloc err\n");
        exit(1);
    }
    petslist[0][0] = malloc(strlen(name) + 1); // allocate memory to contain the owner
    if (petslist[0][0] == NULL) {
        printf("malloc err\n");
        exit(1);
    }
    strcpy(petslist[0][0], name);             // copy owner into the first index

    for (i = 0, j = 1; i < PETAMOUNT; i++) {      // go through all pets 
        if (strcmp(pets[i].owner, name) == 0) {   // if the owner of the current pet is the same as the inputted owner  
            petslist[0] = realloc(petslist[0], (j + 1) * sizeof(char *));   // allocate pointer for the next pet
            petslist[0][j] = malloc(strlen(pets[i].petName) + 1);           // allocate memory to contain the chars of the pet
            if (petslist[0][j] == NULL) {
                printf("malloc err\n");
                exit(1);
            }
            strcpy(petslist[0][j], pets[i].petName);    // copy the petname into the array
            j++;
        }
    }

    puts("petslist:");              // print it all out
    for (i = 0; i < j; i++) {
        printf("|%s|\n", petslist[0][i]);
    }

    exit(0);

    }

目前我总是写到[0] [0],但是如果你重新分配,你可以在那之后腾出更多空间