簡體   English   中英

帶循環的結構和內存分配

[英]Struct and memory allocation with loop

我一直試圖在最后釋放()內存,但是我的教練說我已經創建了3個malloc指針(使用當前設置)。

注意:我想盡可能詳細地解釋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;
    }

我的輸出-

Item Weight Cals
-----------------
apple  4   100
salad  2    80
hello  22   33
maybe  44   45
right 100   200

我認為您的講師對3個malloc字符串的評論是一個很強的線索。 我注意到您有5個項目的數組,其中2個項目已預先填充。 5-2是3。

另外,請注意,C中的索引從0開始。使用數組預初始化的2個項目的索引為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
}

換句話說,循環內的代碼執行了3次,即, 您調用malloc 3次

同樣,查看釋放內存的循環。

for (loopCount = 0; loopCount < LUNCH_ITEMS; loopCount++)
{
    // you execute this code for
    // loopCount equal to 0, 1, 2, 3 and 4

    // ....

    if (loopCount > REMAINING)
    {
        // Since REMAINING is 2, you execute this code for
        // loopCount equal 3 and 4
    }
}

所以在體內的代碼if僅執行2次。 您確實要執行3次(即loopCount等於2、3和4)。 因此,您需要將代碼更改為:

    if (loopCount >= REMAINING)  // Notice the = sign
    {
        // Since REMAINING is 2, you execute this code for
        // loopCount equal 2, 3 and 4
    }

現在關於mallocfree 釋放內存(即使用free必須准確傳遞malloc返回給您的值

在初始化中,您保存了指針,如下所示:

namePtr = (char *)malloc(exactMemory * sizeof(char));
// ...
(lunch + loopCount)->name = namePtr;  // Save pointer

所以(lunch + loopCount)->name應該free 喜歡:

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

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

BTW:請注意

(lunch + loopCount)->name

是相同的

lunch[loopCount].name

許多人認為它更易於閱讀。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM