我正在尝试刷新我对C的记忆。我有一个简单的程序,它检查文本文件中的HTML标记,以确保它们彼此匹配。我为此使用了一个堆栈。这是有问题的代码:
char *tag, *endTag;
stackADT stack = newStack();
while (!feof(input))
{
tag = (char *)malloc(sizeof(char));
tag = getNextTag(input, &line);
printf("tag is %s\n", tag);
if (*(tag + 1) != '/') //if it is not a closing tag
{
push(stack, tag);
printf("%s was pushed\n", tag);
}
else
{
endTag = (char *)malloc(sizeof(char));
endTag = pop(stack);
printf("%s was popped\n", endTag);
check = doTagsMatch(endTag, tag);
if (check == 0)
{
printf("Error at line %d: %s and %s do not match.\n", line, endTag, tag);
exit(1);
}
}
free(tag);
}
从包含html,body和p标签的简单文件中输出如下:
tag is <html>
<html> was pushed
tag is <body>
<body> was pushed
tag is <p>
<p> was pushed
tag is </p>
was popped
Error at line 1: and </p> do not match.
我知道堆栈本身工作正常,因为我做了一个单独的SSCCE有几个整数,它工作正常。这是我使用endTag的程序中唯一的地方,所以我无法弄清楚为什么它没有从pop获得任何东西。我唯一能想到的是它是某种指针问题(我的堆栈元素是空的*,如果重要的话)。
答案 0 :(得分:1)
在每次迭代中,您从tag
分配getNextTag
,然后致电free(tag)
。释放tag
后,它指向的内存内容不再有效(如果您尝试使用它们,C标准不会定义行为)。
您尚未向我们展示push
的定义,但我怀疑它只是记录了传递的值(tag
),并没有复制tag
指向的内容。因此,当您调用pop
时,它会返回按下开始标记时的值tag
,但该值是指向不再有效的内存的指针。
要么push
必须复制它传递的字符串,要么在从堆栈弹出并且不再需要值之后才能调用free(tag)
。 (例如,在弹出标记的else
子句的末尾,同时调用free(endTag)
和free(tag)
。请勿在{{1}的末尾调用free(tag)
}循环。)
此外,这些序列毫无意义且泄漏记忆:
while
在每种情况下,tag = (char *)malloc(sizeof(char));
tag = getNextTag(input, &line);
endTag = (char *)malloc(sizeof(char));
endTag = pop(stack);
或tag
都会分配一个从endTag
返回的值,但该值会被另一个分配立即覆盖。这意味着malloc
返回的值丢失,内存仍然分配但从未使用过。在每种情况下,您都应删除包含malloc
。
答案 1 :(得分:0)
这些行是可疑的
tag = (char *)malloc(sizeof(char));
tag = getNextTag(input, &line);
因为你覆盖了刚从malloc收到的指针。然后,你只分配一个char,这也可能是错误的。
稍后会为endTag复制类似的模式。
也许malloc应该由getNextTag完成(或者你应该将malloc-ed区域作为参数赋予函数),并且它必须不小于标签的长度(加上字符串终止符为1),例如: sizeof(char) * (length+1)
(sizeof(char) == 1
所以你可以省略它。)
然后你释放tag
(错误的,因为你没有释放你分配的东西),但不是endTag ......