2014-10-18 83 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

相关问题