-1

我正在尝试刷新我对 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 中得到任何东西。我唯一能想到的是它在某种程度上是一个指针问题(如果重要的话,我的堆栈元素是 void*)。

4

2 回答 2

1

在每次迭代中,您分配tagfromgetNextTag和之后的 call free(tag)。一旦你 free tag,它指向的内存内容就不再有效(如果你尝试使用它们,C 标准没有定义行为)。

您没有向我们展示 的定义push,但我怀疑它仅记录了它传递的值 ( tag),并没有复制tag指向的内容。因此,当您调用 时pop,它会返回tag推入开始标记时的值,但该值是指向不再有效的内存的指针。

要么push必须复制它传递的字符串,要么free(tag)在值从堆栈中弹出并且不再需要之前不得调用。(例如,在else弹出标签的子句末尾,同时调用free(endTag)free(tag)。不要free(tag)while循环结束时调用。)

此外,这些序列毫无意义并且会泄漏内存:

tag = (char *)malloc(sizeof(char));
tag = getNextTag(input, &line);

endTag = (char *)malloc(sizeof(char));
endTag = pop(stack);

在每种情况下,tagorendTag都被分配了一个从 中返回的值malloc,但该值会立即被另一个分配覆盖。这意味着由返回的值malloc丢失,并且内存保持分配但从未使用过。在每种情况下,您都应该删除包含malloc.

于 2013-06-06T06:01:38.830 回答
0

这些线是可疑的

tag = (char *)malloc(sizeof(char));
tag = getNextTag(input, &line);

由于您覆盖了刚刚从 malloc 收到的指针。然后,您只分配 1 个字符,这也可能是错误的。

稍后为 endTag 复制类似的模式。

也许 malloc 应该由 getNextTag 完成(或者您应该将 malloc-ed 区域作为参数提供给函数),并且它必须不小于标签的长度(字符串终止符加 1),例如sizeof(char) * (length+1)sizeof(char) == 1所以你可以省略)。

然后你释放tag(错误地,因为你没有释放你分配的东西),但不是 endTag ...

于 2013-06-06T06:06:28.223 回答