首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >代码解析中的分段错误

代码解析中的分段错误
EN

Stack Overflow用户
提问于 2015-05-19 04:58:19
回答 1查看 510关注 0票数 0

我有这样的代码,它在两个指定的字符串之间提取字符串,特别是<title></title>。但是当我运行这个程序时,我得到了Segmentation Fault: 11的解决方案吗?

代码语言:javascript
复制
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);

}
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2015-05-19 05:31:43

这里有很多问题。

不按特定顺序:

  • 您正在双释放output (在找到字符串的情况下)。这很可能引发分段错误,尽管不一定是在第二次调用free时。您还在释放bytes,即使它不是从malloc返回的地址(在递归的解析调用中)。这也会导致问题,而且设计也很糟糕:函数通常不应该释放作为参数传递给它们的字符串。
  • 在解析器中,您调用的是文件内容的stat,而不是文件名。这通常会失败,size将毫无意义。这是特别惊人的,因为你实际上不需要的大小。
  • 您可能不想使用strncpy。除非在原始文件中找到NUL,否则strncpy不会空终止副本。所以你最终得到了一个未终止的副本,这可能会造成各种各样的破坏。 相反,只需使用memcpy (它也不为null终止,但至少不会欺骗您认为它可能)并自己添加NUL。
  • 最初从文件中读取的字符串不会以NUL结尾。因此,strstr将在字符串结束后继续读取。
  • parser是递归的,而不是尾递归的.可以很容易地将其编写为尾递归,在这种情况下,您的C编译器可能能够应用TCO,但正如所写的那样,它具有建立大型调用堆栈的潜力。
  • parser不会在对结果调用strstr之前验证第一个strstr是否找到了一个字符串。因此,当没有更多的<title>可供查找时,您将调用ptr2 = strstr(NULL, "</title>");。这肯定会导致断层。

以下是一些可能有用的代码:

代码语言:javascript
复制
/* 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);
        }
    }
}

这也不是最好的代码。但它展示了一些你可以思考的事情。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30317077

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档