2014-10-18 1 views
1

이전에 몇 가지 질문을했지만 문제의 근본 원인을 찾은 것 같습니다. , 방법은 다음 FREELIST의 목록을 무료로 사용할 수있는 새로운 문자열을 요청하도록되어 한 번 루프를 통해 실행 한 후C : 내가 원하는 것 이상 자유롭게 해 주시겠습니까?

for (;;) { 
    printf ("(%d)$ ", ncmd);    // Prompt for command 
    if ((line = getLine(stdin)) == NULL) // Read line 
     break;        // Break on end of file 

    cmd = hExpand (line, &status);   // Expand line 
    free (line); 
    if (status > 0)       // Substitution? 
     fputs (cmd, stdout);    // Print expanded line 
    else if (status < 0) 
     fputs ("substitution failed\n", stderr); 

    list = lex (cmd);      // Lex line into tokens 
    free (cmd); 
    if (list == NULL)      // Empty token list? 
     continue; 

    hRemember (ncmd, list);     // Remember command 
    if (status >= 0)      // No substitution error? 
     process (list);      // Process token list 

    freeList (list);      // Free token list 
    ncmd++;         // Adjust prompt 
    } 

:

나는이 루프를 포함하는 프로그램 mainLex.c이 명부. 이것은 모두 좋고 좋지만, 나는 freeList가 내가 그것을 요구하지 않는 것들을 자유롭게하고 있음을 발견하고있다! 특히, 그것은 글로벌 정적 데이터 구조 llist를 해제하고 있으며, 이것이 어떻게 일어나고 있는지 잘 모르겠습니다.

FREELIST의 코드 :

void freeList (token *list) 
{ 
    token *p, *pnext; 
    for (p = list; p; p = pnext) { 
     pnext = p->next; 
     free(p->text); 
     free(p); //This is apparently where the data structure is being freed 
    } 
} 

hRemember :

void hRemember (int ncmd, token *list) 
{ 
    command* curr; 
    curr = (struct command *)malloc(sizeof(struct command)); 
    token *list1 = malloc(sizeof(token)); 
    list1=list; 
    f = ncmd; 
    curr->cmmd=(struct token *)malloc(sizeof(struct token)); 
    curr->cmmd=list1; 
    curr->num=ncmd; 
    curr->prev=llist; 
    if (llist==NULL) 
    { 
     llist = (struct command *)malloc(sizeof(struct command)); 
    } 
    llist->nextcmd=curr; 
    llist=curr; 
} 

llist가 :

typedef struct command {   // Struct for each token in linked list 
    token *cmmd;     // String containing token 
    int num;      // Corresponding type 
    struct command *prev; 
    struct command *nextcmd;  // Pointer to next token in linked list 
} command; 


command* llist = NULL; //This is global in a different c file than the loop 

내가 루프의 한 버전 이후 llist의 내용을 읽으려고하면, 이것이 무슨 일이 올지 :

==12878== Invalid read of size 8 
==12878== at 0x400DB5: hDump (Lex1.c:153) 
==12878== by 0x400BA9: process (mainLex.c:66) 
==12878== by 0x400B0C: main (mainLex.c:41) 
==12878== Address 0x51f34f0 is 0 bytes inside a block of size 24 free'd 
==12878== at 0x4C29577: free (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) 
==12878== by 0x400C0E: freeList (mainLex.c:81) 
==12878== by 0x400B18: main (mainLex.c:43) 
==12878== 
==12878== Invalid read of size 1 

가능한 경우 루프 또는 freeList를 변경하지 않습니다.

편집 : 렉스 루틴, llist를 사용한다 (나는 많은이를 정리해야하지만, 현재로서는 기능입니다) hRemember에서

token *lex (const char *line) 
{ 
    if (strcspn(line, METACHARS)==strlen(line)) 
    { 
     token *head, *temp, *right, *temp1; 
     char *line1 = strdup(line); 
     char *curr = separate(line1); 
     temp = (token *)malloc(sizeof(token)); 
     temp->text=strdup(curr); 
     temp->type=10; 
     head=temp; 
     head->next=NULL; 
     curr=separate(NULL); 
     while (curr!=NULL) 
     { 
      temp1 = (token *)malloc(sizeof(token)); 
      right = head; 
      while (right->next != NULL) 
      { 
       right=right->next; 

      } 
      temp1->text=strdup(curr); 
      temp1->type=10; 
      temp1->next=NULL; 
      right->next=temp1; 
      curr=separate(NULL); 
     } 
     return head; 
    } 
    else 
    { 
     token *head, *temp, *right, *temp1; 
     char *line1 = strdup(line); 
     char *curr = separate(line1); 
     temp = (token *)malloc(sizeof(token)); 
     temp->text=strdup(curr); 
     if (strcmp(temp->text,"<")==0) 
     { 
      temp->type=20; 
     } 
     else if (strcmp(temp->text,"<<")==0) 
     { 
      temp->type=21; 
     } 
     else if (strcmp(temp->text,"|")==0) 
     { 
      temp->type=30; 
     } 
     else if (strcmp(temp->text,">")==0) 
     { 
      temp->type=31; 
     } 
     else if (strcmp(temp->text,">>")==0) 
     { 
      temp->type=32; 
     } 
     else if (strcmp(temp->text,";")==0) 
     { 
      temp->type=40; 
     } 
     else if (strcmp(temp->text,"&")==0) 
     { 
      temp->type=41; 
     } 
     else if (strcmp(temp->text,"&&")==0) 
     { 
      temp->type=42; 
     } 
     else if (strcmp(temp->text,"||")==0) 
     { 
      temp->type=43; 
     } 
     else if (strcmp(temp->text,"(")==0) 
     { 
      temp->type=50; 
     } 
     else if (strcmp(temp->text,")")==0) 
     { 
      temp->type=51; 
     } 
     else 
     { 
      temp->type=10; 
     } 

     head=temp; 
     head->next=NULL; 
     curr=separate(NULL); 
     while (curr!=NULL) 
     { 
      temp1 = (token *)malloc(sizeof(token)); 
      right = head; 
      while (right->next != NULL) 
      { 
       right=right->next; 

      } 
      temp1->text=strdup(curr); 
      if (strcmp(temp1->text,"<")==0) 
      { 
       temp1->type=20; 
      } 
      else if (strcmp(temp1->text,"<<")==0) 
      { 
       temp1->type=21; 
      } 
      else if (strcmp(temp1->text,"|")==0) 
      { 
       temp1->type=30; 
      } 
      else if (strcmp(temp1->text,">")==0) 
      { 
       temp1->type=31; 
      } 
      else if (strcmp(temp1->text,">>")==0) 
      { 
       temp1->type=32; 
      } 
      else if (strcmp(temp1->text,";")==0) 
      { 
       temp1->type=40; 
      } 
      else if (strcmp(temp1->text,"&")==0) 
      { 
       temp1->type=41; 
      } 
      else if (strcmp(temp1->text,"&&")==0) 
      { 
       temp1->type=42; 
      } 
      else if (strcmp(temp1->text,"||")==0) 
      { 
       temp1->type=43; 
      } 
      else if (strcmp(temp1->text,"(")==0) 
      { 
       temp1->type=50; 
      } 
      else if (strcmp(temp1->text,")")==0) 
      { 
       temp1->type=51; 
      } 
      else 
      { 
       temp1->type=10; 
      } 
      temp1->next=NULL; 
      right->next=temp1; 
      curr=separate(NULL); 
     } 
     return head; 
    } 
} 
+0

내가 당신의'list' 객체의 이름을 바꾸는 생각 하는데요 'my_list'일지라도. 내 머리 속의 파서는'std :: list'와 혼동을 계속합니다. 어쩌면'token_list'는 좋은 이름일까요? – Baldrickk

답변

1

당신은이 :

curr->cmmd=(struct token *)malloc(sizeof(struct token)); 
curr->cmmd=list1; 

당신은 할당 메모리를 할당 한 다음 할당 후 바로 -> cmmd에 다른 포인터를 할당하여 누출시킵니다. 메모리를 복사해야합니다. 그렇지 않으므로 -> cmmd가 주 루프의 free()과 같은 주소에 할당 된 다음 루프가 끝나면이 포인터는 더 이상 유효한 메모리를 가리 키지 않습니다.

당신이 있어야합니다

curr->cmmd=(struct token *)malloc(sizeof(struct token)); 
memcpy(curr->cmmd, list1, sizeof(struct token)); 

같은 문제, 다른 장소, 선을 :

llist->nextcmd=curr; 

은 다음과 같아야합니다

memcpy(llist->nextcmd, curr, sizeof(struct command)); 
+0

고마워요, 그건 많은 의미가 있습니다. 그것은 내 모든 문제를 해결하지 못했지만, 나는이 같은 다른 문제들이 똑같은 것과 관련되어 있다는 몰래 의심을 가지고 있습니다. –