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

标签 c arrays memory-management struct

所以...过去有人告诉我我的问题不好...我相信主要是因为我没有足够好地隔离出有问题的代码。在这篇文章中,我会尽我所能提出一个尖锐、简洁、切题的问题。我当然愿意接受有关如何更好地提出我的问题的建议。 谢谢。

我正在用 C 语言开发一个小项目,该项目将用作我已经开发了一段时间的大型错误程序的原型(prototype)。我试图先在一个较小的程序中计算出细节。我有两个结构:

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;

该程序应该从用户输入中获取 ownerName,并将其与 pets 结构中的“.owner”进行比较。然后应该将 ownerName 和 petName 元素复制到一个数组中,并且主人和他/她的宠物的名字将被打印在一个列表中。虽然我知道我不需要所有者结构来完成此操作,但我正在使用它来为我正在编写的其他程序建模。

我在用

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

比较结构元素,似乎把这部分放下了。

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

char *petsList[l];

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

我还通过以下方式创建了一个指向 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 次运行良好,但在第四次失败,因此看起来循环的最后一次迭代始终失败。我曾多次尝试更改代码,但现在对如何推进该程序感到茫然。任何帮助是极大的赞赏。

谢谢。

最佳答案

不要转换 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] 但如果你重新分配你可以在那之后腾出空间

关于c - 最后一次循环迭代的内存分配失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27045764/

相关文章:

c - 为什么我们不能使用静态变量来实现尾递归呢?

调用 open(2) 会忽略 S_IWGRP 和 S_IWOTH 标志

php - 如何在 php 中使用 in_array 作为子数组?

javascript - 在二维数组中查找比较

c++ - 内存没有正确对齐?

c - 错误: dereferencing pointer to incomplete type in main file

c - 什么时候使用 fopen 而不是 open?

php - 为什么我的 php 数组作为对象保存到 MongoDB,然后作为带有字符串化键的关联数组进行检索?

c++ - 为什么 realloc 会使我的自定义分配器数据无效?

java - 我如何通过 JMX 计算出 PS Old Gen 上的垃圾收集计数?