我有一个C代码(我编写的第一个C代码),并且有一个错误,但我不知道,在哪里。当我尝试释放一个变量(dinamically allocate,它的名字是out_html)时,我得到双重免费或腐败。我不知道为什么我的程序会这样做,我检查了所有免费电话等。
代码:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <math.h>
#include "fcntl.h"
#include "errno.h"
#include "sys/types.h"
#include "sys/stat.h"
#include "unistd.h"
#define MAX_SIZE 512
typedef struct node
{
char* data;
struct node * nextnode;
} node;
int max(int a, int b)
{
if(a>b) return a;
else return b;
}
node* push(node * stackTop, char* data)
{
//static
node* newItem;
newItem = calloc(sizeof(node),1);
newItem->data = data;
newItem->nextnode = stackTop;
return newItem;
}
node* pop(node* stackTop)
{
if(stackTop != NULL)
{
free(stackTop->data);
node* P = stackTop;
return stackTop->nextnode;
free(P);
}else return NULL;
}
int isMajorTag(char* tag)
{
if(strcmp(tag, "<html>") == 0 || strcmp(tag, "</html>") == 0 ||
strcmp(tag, "<body>") == 0 || strcmp(tag, "</body>") == 0 ||
strcmp(tag, "<head>") == 0 || strcmp(tag, "</head>") == 0 ) { return 1; }
else { return 0; };
}
int isHTMLtag(char* tag, char* tags)
{
char* tag2;
if(strstr(tag," ") != NULL)
{
char* strptr = strstr(tag, " ");
int End = strptr - tag;
char* tag_ = strndup(tag, End);
tag2 = calloc((strlen(tag_) + strlen("*") + 2), sizeof(char));
strcpy(tag2, tag_);
strcat(tag2,"*");
free(tag_);
}
else tag2 = tag;
int ret;
if(strstr(tags, tag2) != NULL){ ret = 1; }
else { ret = 0; };
if(tag2 != tag ) free(tag2);
return ret;
}
int isCloserTagOf(char* cltag, char* tag)
{
int ret = 1;
if( cltag[1] != '/' ) ret = 0;
if( tag[1] == '/' ) ret = 0;
char* ntag;
char* ncltag;
if(strstr(tag," ") != NULL)
{
char* strptr = strstr(tag, " ");
int End = strptr - tag;
ntag = strndup(tag, End) + 1;
// ntag = calloc(strlen(ntag0) + 1 + 1, sizeof(char)); strcpy(ntag, ntag0); strcat(ntag, ">");
ncltag = strndup(cltag+2,strlen(cltag) - 3);
} else
{
ntag = tag + 1;
ncltag = cltag + 2;
}
// printf("|%s|%s| %i", ntag, ncltag, strcmp(ncltag, ntag));
if(strcmp(ncltag, ntag) != 0) ret = 0;
return ret;
}
int isIndividualTag(char* tag)
{
if(strcmp(tag,"</br>") == 0) return 1;
else if(strncmp(tag,"<!--#include file=",18) == 0) return 2;
else if(strncmp(tag,"<!--#echo var=",14) == 0) return 3;
else if(strncmp(tag,"<!--",4) == 0) return 4;
else return 0;
}
int main(int argc,char *argv[])
{
char* fname;
if(argc == 2)
{
fname = argv[1];
} else
{
printf("Give me a filename!");
fname = calloc( MAX_SIZE, sizeof(char));
scanf("%s", fname);
};
printf("Parameter: %s \n\n", fname);
// beolvasas
int f = open(fname, O_RDONLY);
long pos = lseek(f, 0, SEEK_END);
lseek(f, 0, SEEK_SET);
char *buff = calloc(pos,1);
read(f, buff, pos);
close(f);
f = open("valid-tags", O_RDONLY);
pos = lseek(f, 0, SEEK_END);
lseek(f, 0, SEEK_SET);
char *valids = calloc(pos,1);
read(f, valids, pos);
close(f);
// printf("File: %s %s %i ",buff, valids, isCloserTagOf("</html>","<html>")); printf("Igen? %i", isHTMLtag("</head>",valids));
node* Stack = NULL;
char *P = buff;
int is_valid = 1;
int bodyCnt = 0;
char* body[6];
int correct_body = 1;
char* out_html = calloc(strlen(buff), sizeof(char));
while(P[0] != '\0' )
{
if(P[0] == '<')
{
char* strptr = strstr(P, ">");
if(strptr != NULL)
{
int nextCloser = strptr - P + 1;
char* tag = strndup(P, nextCloser);
int IsIndividual = isIndividualTag(tag);
if(isHTMLtag(tag, valids) || IsIndividual)
{
if(IsIndividual)
{
if(IsIndividual == 2) // file inclusion
{
char* firstQ = strstr(tag, "\"");
char* secondQ;
if( firstQ ) secondQ = strstr(firstQ + 1, "\"");
if( firstQ && secondQ )
{
char* incl_filename = strndup((firstQ + 1), (secondQ - firstQ - 1));
f = open(incl_filename, O_RDONLY);
pos = lseek(f, 0, SEEK_END);
lseek(f, 0, SEEK_SET);
char *inclstr = calloc(pos,1);
read(f, inclstr, pos);
close(f);
char* new_out_html = calloc((max(strlen(buff),strlen(out_html)) + pos + 1 + 1 + 1), sizeof(char));
strcpy(new_out_html, out_html);
strcat(new_out_html, inclstr);
free(out_html); out_html = NULL; // free(inclstr);
out_html = new_out_html;
} else
{
printf("Invalid file inclusion! \n");
is_valid = 0; break;
};
} else if (IsIndividual == 3) // date time
{
time_t t = time(NULL);
// int nDigits = floor(log10(abs(t)) + 1; (strlen(out_html) + nDigits
char* timestring = ctime(&t);
char* new_out_html = calloc(1 + max(strlen(buff),strlen(out_html)) + strlen(timestring), sizeof(char));
strcpy(new_out_html, out_html);
strcat(new_out_html, timestring);
//printf("%s",new_out_html);
free(out_html); out_html = NULL; // free(timestring);
out_html = new_out_html;
} else
{
strcat(out_html, tag);
};
}else
{
strcat(out_html, tag);
if(Stack != NULL && isCloserTagOf(tag,Stack->data))
{
Stack = pop(Stack);
}else
{
Stack = push(Stack, tag);
};
}
if(isMajorTag(tag))
{
if(bodyCnt < 6)
{ body[bodyCnt] = calloc(strlen(tag), sizeof(char));
strcpy(body[bodyCnt],tag);
++bodyCnt;
}else
{
printf("Too much major html tag found...");
correct_body = 0;
}
}
}else
{
printf("Invalid html tag: %s \n", tag);
is_valid = 0;
break;
}
P = P + nextCloser;
}
else
{
printf("Unclosed tag\n");
is_valid = 0;
break;
}
} else
{ //printf("-%c",P[0]);
strncat(out_html, P,1);
// printf("{(%s)}",out_html);
P = P + 1;
};
};
int i;
char* correctBody[] = { "<html>", "<head>", "</head>", "<body>", "</body>", "</html>"};
for(i = 0; i < bodyCnt && correct_body; ++i) {
correct_body = (strcmp(body[i],correctBody[i]) == 0); }
if(is_valid && Stack == NULL &&
correct_body && bodyCnt == 6){ printf("\nValid HTML Code\n");
printf("\n\n%s\n",out_html);
}
else printf("\nInvalid.\n");
// printf("%i %i %i",bodyCnt,correct_body,is_valid);
/*****************************************************************/
for(i=0;i<bodyCnt;++i) free(body[i]);
free(buff); free(valids); //
if(out_html != NULL) free(out_html);
return 0;
}
在代码的最后: if(out_html!= NULL)free(out_html); 没有这个,就没有崩溃。
我认为坠机是在第196行附近造成的。
(必须有一个带有正确html标签的valig-html文件 - 没有这个,代码没用,我的意思是这样的文件:)
答案 0 :(得分:1)
很难弄清楚代码中发生了什么,但是第一眼就看到了一些无意义的无意义操作。例如,考虑这个序列
int f = open(fname, O_RDONLY);
long pos = lseek(f, 0, SEEK_END);
lseek(f, 0, SEEK_SET);
char *buff = calloc(pos,1);
read(f, buff, pos);
close(f);
...
char* out_html = calloc(strlen(buff), sizeof(char));
您将某个文件的内容读入已分配的缓冲区buff
(缓冲区的大小正好是文件的大小)。之后您将buff
视为以空字符结尾的字符串:您将其用作strlen
的参数。
但是你从来没有打扰过你的buff
!这应该怎么样?如果它不是以null结尾,则它不是字符串,并且不能有意义地用作strlen
的参数。
你的程序包含几个遵循相同模式的代码实例:某个文件的整个内容被读入一个具有确切大小的缓冲区,然后被解释为以null结尾的字符串,而实际上它不是以null结尾的(没有人为确保无效终止而烦恼。)
终止零是否应该出现在文件本身中?如果是这样,那我们怎么知道呢?我们不是在这里进行远程会议。
答案 1 :(得分:0)
错误消息可能有点令人困惑。
当使用calloc分配200字节时,例程内部分配更多:
说8,16或32个字节来制作链表和其他簿记(即它已被释放)。
如果使用strcpy / strcat附加或复制的字符串不适合目标数组,则内部可能会导致簿记损坏。
因此,错误不一定会释放指针两次。
答案 2 :(得分:0)
这看起来不对: (顺便说一句:我找不到stackTop的定义/声明)
node* pop(node* stackTop)
{
if(stackTop != NULL)
{
free(stackTop->data);
node* P = stackTop;
return stackTop->nextnode;
free(P);
}else return NULL;
}
这是另一个太短的calloc()。 (strcpy()会将其nul字节放在不属于calloc()ed对象的位置.BTW:根据定义,sizeof(char)为1。
if(bodyCnt < 6)
{ body[bodyCnt] = calloc(strlen(tag), sizeof(char));
strcpy(body[bodyCnt],tag);
++bodyCnt;
}else
{
printf("Too much major html tag found...");
correct_body = 0;
}