我之前曾就此问过几个问题,但我认为我找到了问题的根本原因。
我有一个包含这个循环的程序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中释放列表,然后请求新的字符串用作列表。这一切都很好,但我发现freeList正在释放我不会要求它的东西!特别是,它正在释放全局静态数据结构列表,我不确定这是如何发生的。
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。
编辑:lex例程,它使用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 :(得分:1)
hRemember你有:
curr->cmmd=(struct token *)malloc(sizeof(struct token));
curr->cmmd=list1;
您分配内存,然后通过在分配后立即指定一个不同的指针 - &gt; cmmd来泄漏它。你应该复制内存。既然你没有, - &gt; 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));