【问题标题】:Segmentation fault in parsing into linked list解析成链表时出现分段错误
【发布时间】:2015-08-02 12:22:10
【问题描述】:

我有这个程序可以将 RSS 提要解析成一个链表。

#include"util.h"
#include<stdio.h>
#include<stdlib.h>
#include<sys/stat.h>
#include<string.h>

void parse_tc(){

    struct node *head = NULL;
    char *bytes = 0;

    struct stat st;
    stat("techcrunch.txt", &st);

    int size = st.st_size;
    FILE *f = fopen("techcrunch.txt", "rb");

    bytes = (char*)malloc(size + 1);
    size_t nread = fread(bytes,1,size,f);
    bytes[nread] = 0;
    fclose(f);


    struct node *temp = (struct node*)malloc(sizeof(struct node));
    temp->position = 1;
    printf("%d. ", temp->position);
    char *a = title_parser_tc(bytes,temp);
    head = temp;

    for(int i = 2; i<21; i++){
            temp = (struct node*)malloc(sizeof(struct node));
            temp->position = i;
            printf("%d. ", temp->position);
            a = title_parser_tc(a, temp);
            struct node* temp1 = head;

            while(temp1->link != NULL)
            {
                    temp1 = temp1->link;
            }
            temp1->link = temp;

    }

    free(bytes);
    int holder = 0;
    int check = 0;
    do {
            printf("Enter a number: ");
            scanf("%d", &holder);
            if(holder<1 || holder > 20){
                    puts("Invalid input");
                    check = 1;
            }
            else{
                    check = 0;
            }
    } while(check);

    get_feed(holder, head);
}

char* title_parser_tc(char *bytes, struct node *temp){


    char *ptr = strstr(bytes, "<title>");

    if (ptr) {

            ptr += 7;
            char *ptr2 = strstr(ptr, "</title>");

            if (ptr2) {

                    char* output = malloc(ptr2 - ptr + 1);
                    memcpy(output, ptr, ptr2 - ptr);
                    output[ptr2 - ptr] = 0;

                    if(strcmp(output,"TechCrunch")!=0){

                            temp->title = output;
                            puts(temp->title);
                            temp->link = NULL;free(output);

                            char *load = pubdate_parser_tc(ptr2, temp);
                            return load;
                    }
                    else{

                            char *load = title_parser_tc(ptr2, temp);
                            free(output);
                            return load;
                    }
            }
    }
    return NULL;
}

char* pubdate_parser_tc(char *bytes, struct node *temp){

    char *ptr = strstr(bytes, "<pubDate>");

    if (ptr) {

            ptr += 9;
            char *ptr2 = strstr(ptr, "</pubDate>");

            if (ptr2) {
                    char* output = malloc(ptr2 - ptr + 1);
                    memcpy(output, ptr, ptr2 - ptr);
                    output[ptr2 - ptr] = 0;
                    temp->pubdate = output;
                    free(output);
                    char *load = description_parser_tc(ptr2, temp);
                    return load;

            }
    }
    return NULL;
}

char* description_parser_tc(char *bytes, struct node *temp){

    char *ptr = strstr(bytes, "<description>");

    if (ptr) {

            ptr += 13;
            char *ptr2 = strstr(ptr, "</description>");
            if (ptr2){
                    char* output = malloc(ptr2 - ptr + 1);
                    memcpy(output, ptr, ptr2 - ptr);

                    output[ptr2 - ptr] = 0;
                    description_cleaner_tc(output, temp);
                    free(output);

                    char *load = url_parser_tc(ptr2, temp);
                    return load;
            }
    }
    return NULL;
}

void description_cleaner_tc(char *bytes, struct node *temp){

    char *ptr = strstr(bytes, "&amp;nbsp;");

    if (ptr) {

            ptr += 10;
            char *ptr2 = strstr(ptr, "&lt;a ");
            if (ptr2) {
                    char* output = malloc(ptr2 - ptr + 1);
                    memcpy(output, ptr, ptr2 - ptr);
                    output[ptr2 - ptr] = 0;
                    temp->description = output;
                    puts(temp->description);
                    free(output);
            }
    }
}

char* url_parser_tc(char *bytes, struct node *temp){
    char *ptr = strstr(bytes, "href");

    if (ptr) {

            ptr += 6;
            char *ptr2 = strstr(ptr, "&gt;");

            if (ptr2) {
                    char* output = (char*)malloc(ptr2 - ptr);
                    memcpy(output, ptr, ptr2 - ptr - 1);
                    output[ptr2 - ptr - 1] = 0;
                    temp->url = output;
                    puts(temp->pubdate);
                    puts(temp->url);
                    puts("");
                    free(output);
                    return ptr2;
            }
    }
    return NULL;
}

我的问题是对于这个文件textcrunch.txt,我的程序在parse_tc() 的第10 个循环左右发生了分段错误。该程序适用于另一个文件,但这个文件给了我一个错误。有什么解决办法吗?

代码基本上是对要解析的不同字符串重复相同的函数。

【问题讨论】:

  • char *ptr = strstr(bytes, "href"); ... ptr += 6;。为什么是 6 个?
  • 如果The program works for another file but this file gives me an error,那么您需要提供一个有效文件的内容和一个无效文件的内容,以便我们自己尝试。否则我们可能会选择一个有效的文件。
  • for(int i = 2; i&lt;21; i++) ptr += 7; ptr += 9; 似乎是神奇的数字:它们是否适用于所有情况???
  • 如果您的程序输入格式错误的 HTML 或跨越多行的标签会发生什么?我也会让你的标签常量和 strlen() 他们摆脱魔术数字。
  • 此代码会产生 几十个 的编译器警告或错误消息。其中大部分与我不知道您的 util.h 头文件中包含什么这一事实无关。因此,首先,阅读编译器的输出,并将其用作您的指南。按照目前的情况,这个问题可能会被关闭,因为它只是关于调试你的程序,而不是关于开发对整个社区有用的有用问题和答案。你的代码应该被重写为Minimal, Complete, and Verifiable example

标签: c parsing segmentation-fault


【解决方案1】:

分段错误通常意味着取消引用空指针(或指向未初始化内存的指针)。如果您使用的是 GCC 或 Clang,您可以使用 -g 标志重新编译并通过 gdb 运行生成的程序:

gdb --args ....
r
bt

第一行启动 gdb,提供您通常运行的命令。 r 开始运行,bt 从程序因分段错误停止的点开始提供回溯。至少这可以为您提供代码中发生问题的位置。您可以从 print 语句开始进一步调试,或者在那里添加一些防御性代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-05-18
    • 2017-11-24
    • 1970-01-01
    • 1970-01-01
    • 2015-06-12
    相关资源
    最近更新 更多