2014-10-18 82 views
1

以前我已經問過幾個關於這方面的問題,但我想我找到了問題的根源。C:免費獲得比我想要的更多的空間

我有一個包含該循環的程序mainLex.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 
    } 

通過循環運行一次後,該方法應該是自由空閒列表清單,然後要求新的字符串作爲使用名單。這一切都很好,但我發現freeList釋放了我沒有要求的東西!特別是,它釋放了全局靜態數據結構llist,我不確定這是如何發生的。

爲空閒列表的代碼:

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(我需要打掃一下了很多,但它的功能,截至目前)

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 2014-10-22 07:42:21

回答

1

在hRemember您有:

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

謝謝,這很有道理。看來它並沒有解決我所有的問題,但我懷疑這些其他問題與同一事物有關。 – 2014-10-18 21:25:42

相關問題