我有这样的代码,它在两个指定的字符串之间提取字符串,特别是<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);
}发布于 2015-05-19 05:31:43
这里有很多问题。
不按特定顺序:
output (在找到字符串的情况下)。这很可能引发分段错误,尽管不一定是在第二次调用free时。您还在释放bytes,即使它不是从malloc返回的地址(在递归的解析调用中)。这也会导致问题,而且设计也很糟糕:函数通常不应该释放作为参数传递给它们的字符串。stat,而不是文件名。这通常会失败,size将毫无意义。这是特别惊人的,因为你实际上不需要的大小。strncpy。除非在原始文件中找到NUL,否则strncpy不会空终止副本。所以你最终得到了一个未终止的副本,这可能会造成各种各样的破坏。
相反,只需使用memcpy (它也不为null终止,但至少不会欺骗您认为它可能)并自己添加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);
}
}
}这也不是最好的代码。但它展示了一些你可以思考的事情。
https://stackoverflow.com/questions/30317077
复制相似问题