我有这段代码,专门提取两个指定字符串<title>
和</title>
之间的字符串。但是当我运行该程序时,我得到Segmentation Fault: 11
任何解决方案?
int main(){
struct stat st;
stat("test.txt", &st);
int size = st.st_size;
printf("%d\n", size);
FILE *f = fopen("test.txt", "rb");
char *bytes = (char*)malloc(size);
fread(bytes,size,1,f);
fclose(f);
parser(bytes);
return 0;
}
void parser(char *bytes){
struct stat st;
stat(bytes, &st);
int size = st.st_size;
char *output = (char*)malloc(size);
char *ptr = strstr(bytes, "<title>");
char *ptr2 = strstr(ptr, "</title>");
if(ptr2){
strncpy(output, ptr+7, (ptr2 - (ptr+7)));
puts(output);
free(output);
parser(ptr2);
}
free(bytes);
free(output);
}
答案 0 :(得分:3)
这里有很多问题。
没有特别的顺序:
你是双重释放output
(在你找到一个字符串的情况下)。这极有可能引发一个段错误,尽管不一定是第二次调用free
时。即使它不是从bytes
返回的地址(在递归调用解析中),您也可以释放malloc
。这也会导致问题,而且设计很糟糕:函数通常不应该释放作为参数传递给它们的字符串。
在解析器中,您正在调用文件内容stat
,而不是文件名。这通常会失败,而size
将毫无意义。这是特别令人震惊的,因为你实际上并不需要这么大。
您可能不想使用strncpy
。除非在原始文件中找到NUL,否则strncpy
不会终止副本。所以你最终会得到一个未终止的副本,这可能会造成各种各样的破坏。
相反,只需使用memcpy
(它也不会终止,但至少它不会让你误以为它可能)并自己添加NUL。
您最初从文件中读取的字符串不是NUL终止的。因此strstr
将继续阅读超出字符串末尾的内容。
parser
是递归的,而不是尾递归。它可以很容易地被编写为尾递归,并且在这种情况下你的C编译器可能能够应用TCO,但是正如所写,它有可能构建一个大的调用堆栈。
parser
未在结果上调用strstr
之前验证第一个strstr
是否找到了字符串。因此,当找不到<title>
时,您将调用ptr2 = strstr(NULL, "</title>");
。那肯定是段错误。
以下是一些可能有用的代码:
/* Forward declare parser */
void parser(char *bytes);
int main(){
struct stat st;
stat("test.txt", &st);
/* CHECK RETURN VALUE */
int size = st.st_size;
printf("%d\n", size);
FILE *f = fopen("test.txt", "rb");
/* CHANGE: need space for the NUL */
char *bytes = malloc(size + 1);
size_t nread = fread(bytes,size,1,f);
if (nread != size) { /* HANDLE ERROR */ }
/* CHANGE: NUL terminate string */
bytes[nread] = 0;
fclose(f);
parser(bytes);
/* CHANGE: We allocated bytes, we free it */
free(bytes);
return 0;
}
void parser(char *bytes){
char *ptr = strstr(bytes, "<title>");
/* CHANGE: Make sure strstr found something */
if (ptr) {
/* Skip over the found string */
ptr += 7:
char *ptr2 = strstr(ptr, "</title>");
if (ptr2) {
/* Don't allocate buffer until we need it */
/* Remember to leave space for the NUL */
char* output = malloc(ptr2 - ptr + 1);
memcpy(output, ptr, ptr2 - ptr);
/* null-terminate */
output[ptr2 - ptr] = 0;
puts(output);
free(output);
parser(ptr2);
}
}
}
这也不是最好的代码。但它显示了一些你能想到的事情。