C 带循环的结构和内存分配

C 带循环的结构和内存分配,c,struct,memory-leaks,malloc,dynamic-memory-allocation,C,Struct,Memory Leaks,Malloc,Dynamic Memory Allocation,我一直试图在最后释放()内存,但是我的导师说我已经创建了3个malloc'd指针(使用当前设置) 注意:我希望尽可能详细地解释malloc/内存中实际发生了什么 我希望您能指导我如何确保没有内存泄漏 我写了以下内容 #include <stdio.h> #include <stdlib.h> #include <string.h> #define LUNCH_ITEMS 5 #define REMAINING 2

我一直试图在最后释放()内存,但是我的导师说我已经创建了3个malloc'd指针(使用当前设置)

注意:我希望尽可能详细地解释malloc/内存中实际发生了什么

我希望您能指导我如何确保没有内存泄漏

我写了以下内容

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

    #define LUNCH_ITEMS 5
    #define REMAINING 2
    #define CHAR_SIZE 256

    int main(void)
    {
        struct Food
        {
            char *name; //name attribute of food
            int weight, calories;
        } lunch[LUNCH_ITEMS] = {{"apple", 4, 100}, {"salad", 2, 80},};
        int loopCount;
        //INPUT
        char *namePtr = NULL;
        for (loopCount = REMAINING; loopCount < LUNCH_ITEMS; ++loopCount)
        {
            char tempBuffer[CHAR_SIZE];
            printf("Enter name of item,the weight of item, and the calories in that item: \n");
            // store name string in a tempBuffer. weight and calories directly into lunch structure array address
            scanf("%255s %d %d", tempBuffer, &lunch[loopCount].weight, &lunch[loopCount].calories);
            // get the exact size of (memory of) the input string including add one for null char
            size_t exactMemory = strlen(tempBuffer) + 1;
            //dynamically allocate the exact amount of memory determined in the previous step
            namePtr = (char *)malloc(exactMemory * sizeof(char));
            // check if no memory is allocated for foodPtr
    if (namePtr == NULL)
    {
        fprintf(stderr, "Not enough memory available***\n Terminating Program");
        exit(1);
    }
    //store the pointer to it in the name member of the structure in
    //the current lunch array element.
    (lunch + loopCount)->name = namePtr;
    // Copy the food name (stored in tempbuffer) into the dynamically-allocated
    // memory using the memcpy function

            memcpy(namePtr, tempBuffer, exactMemory);
    //(lunch + loopCount)->name = namePtr;
        }
    //DISPLAY
        printf("Item                        Weight       Cals\n---------------------------------------------\n");
        for (loopCount = 0; loopCount < LUNCH_ITEMS; loopCount++)
        {
            int weight = lunch[loopCount].weight;
            int cals = lunch[loopCount].calories;
            printf("%-12.20s%22d%11d\n", (lunch + loopCount)->name, weight, cals);
            if (loopCount > REMAINING)
            {
                //(lunch+loopCount)->name = NULL;
                namePtr = NULL;
                free(namePtr);
                //free((lunch + loopCount)->name);
            }
        }
        //De-allocate all malloc'd memory
        return EXIT_SUCCESS;
    }

我认为你的导师关于3个malloc'ed字符串的评论是一个非常有力的线索。我注意到您有一个由5项组成的数组,其中预填充了2项。5-2等于3


另外,请注意C中的索引从0开始。预先初始化数组时使用的两个项将具有索引0和索引1。索引2将是第一个输入的数据。使用>2比较该索引实际上会导致跳过用户提供的第一条数据的索引。

查看初始化循环:

for (loopCount = REMAINING; loopCount < LUNCH_ITEMS; ++loopCount)
{
    // The code inside the loop will be executed for
    // loopCount being equal to 
    //     REMAINING
    //     REMAINING + 1
    //     ....
    //     LUNCH_ITEMS - 1
    //
    // So in your case, you execute this code for
    // loopCount equal to 2, 3 and 4
}
现在关于
malloc
free
。释放内存时,即使用
free
必须准确传递malloc返回给您的值

在初始化过程中,您保存了如下指针:

namePtr = (char *)malloc(exactMemory * sizeof(char));
// ...
(lunch + loopCount)->name = namePtr;  // Save pointer
因此,应将
(午餐+循环计数)->name
用于
免费
。比如:

    if (loopCount >= REMAINING)  // Notice the = sign
    {
        free((lunch + loopCount)->name);

        // Optional part but always after calling free
        (lunch + loopCount)->name = NULL;
    }
顺便说一句:注意

(lunch + loopCount)->name

lunch[loopCount].name

许多人认为读起来更容易。

ValgRink是一个很好的工具,用来检查程序是否泄露内存或做其他不明智的事情。在你的程序中使用valgrind可能会暴露出几个问题。既然别人会指出,我就这么做:。注意:
strcpy
(甚至
strncpy
)可能比
memcpy
更清楚你的意图。至于实际问题:你在循环中运行
malloc
,这会发生三次。因此,您有三个
malloc
-ed内存项。您确实释放了它们,但我认为您只剩下一个:
loopcount>剩余的
将错过第三个午餐项目(index
[2]
),其名称是用malloc动态分配的。将指针设置为null,然后将其设置为
free
ing显然是不正确的。当我运行程序时,程序当前已完成,并且所有答案都正确,但该类的电子邮件提交更正器说我有动态内存错误。当我将if块中DISPLAY注释下的代码更改为>=REMAINING时,会出现一条错误消息,说明我试图取消分配的点尚未分配。错误是否不在显示区域,而是在我将loopCount设置为“2”的第一个块中?谢谢您的详细解释。我的指导老师让我看起来好像用malloc初始化了3个单独的指针(而不是用malloc创建的)。然后我变得非常困惑,把一切都撕成碎片,开始了几次。非常感谢您对malloc和free如何使用东西的详细解释。在将指针设置为结构的成员后,我不理解malloc的行为方式。另外,感谢您提供了关于如何正确使用NULL的非常有用的方法,我做了很多研究,一定是误解了语法。您的解释也确实澄清了我对free()函数的看法。真的帮助我以一种非常直接的方式理解了我正在编写的代码。
    if (loopCount >= REMAINING)  // Notice the = sign
    {
        free((lunch + loopCount)->name);

        // Optional part but always after calling free
        (lunch + loopCount)->name = NULL;
    }
(lunch + loopCount)->name
lunch[loopCount].name