2017-05-24 3 views
0

나는 강사가 (현재 설정으로) 3 개의 malloc'd 포인터를 만들었다 고 말했지만 결국 메모리를 free()하려고 시도했다.구조체와 메모리 할당 루프

참고 : 실제로 메모리에서 진행되고있는 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 
+0

Valgrind는 프로그램에서 메모리 누출이 있는지 또는 메모리가있는 기타 현명한 일을하는지 확인하는 데 유용한 도구입니다.프로그램에서 valgrind를 사용하면 몇 가지 문제점이 드러날 수 있습니다. – Evert

+0

다른 사람이 지적하기 때문에 나는 그것을 할 것이다 : [malloc의 반환 값을 캐스트하지 말라] (https://stackoverflow.com/questions/1565496/specifically-whats-dangerous-about-casting-the- malloc 결과). – Evert

+0

주 :'strcpy' (또는'strncpy')는 의도적으로'memcpy'보다 더 명확 할 수 있습니다. – Evert

답변

0

봐 : 즉

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 배, I, E, 당신이 3 회의 malloc에게 전화를 실행한다.

마찬가지로 메모리를 해제 한 루프를 살펴보십시오.

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 번 실행됩니다. 번 (즉, 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 

과 동일 함을 알 수 있습니다.

+0

자세한 설명을 해주셔서 감사합니다. 내 강사가 malloc (malloc을 사용하여 생성되는 것이 아니라)으로 3 개의 별도 포인터를 초기화 한 것처럼 보였습니다. 나는 매우 혼란스러워지고 모든 것을 갈가리 찢고 몇 번에 걸쳐 시작했다. malloc과 free가 어떻게 사용되는지에 대한 자세한 설명을 해주셔서 감사합니다. 구조체의 멤버에 포인터를 설정 한 후에 malloc이 작동하는 방식을 이해하지 못했습니다. 또한 올바르게 NULL을 사용하는 방법에 대한 매우 유익한 방법을 주셔서 감사합니다, 나는 많이 연구하고 그래서 구문에 대한 오해가 있어야합니다. – Donner

+0

또한 당신의 설명은 정말로 free() 함수를 보는 방법을 정리했습니다. 필자가 작성한 코드를 이해하는 데 정말로 도움이되었습니다. – Donner

0

내가 강사의 코멘트에 대한 3 malloc 된 문자열을 생각은 꽤 강력한 단서입니다. 나는 당신이 2 항목 미리 채워진 5 품목의 배열을 가지고 있다는 것을 알아 차렸다. 5 - 2는 3입니다.

또한 C의 색인은 0부터 시작합니다. 배열을 사전 초기화하는 두 항목에는 색인 0과 색인 1이 있습니다. 색인 2는 처음 입력 한 데이터가됩니다. 해당 인덱스를> 2를 사용하여 비교하면 실제로 사용자가 제공 한 첫 번째 데이터의 인덱스를 건너 뛸 수 있습니다. 초기화 루프에서

+0

프로그램을 실행할 때 현재 완료되고 모든 답이 맞지만 클래스의 전자 메일 제출 교정자가 동적 메모리 오류가 있다고합니다. 내가 if 블록에서 DISPLAY 주석 아래의 코드를> = REMAINING으로 변경하면 할당을 해제하려고하는 지점에 대한 오류 메시지가 할당되지 않았습니다. 오류가 표시 영역에 있지만 첫 번째 블록에서 loopCount를 '2'로 설정 했습니까? – Donner