简体   繁体   English

尝试制作链表,出现段错误

[英]Trying to make linked list, getting seg fault

New to C, but I'm trying to write this Linked List program, and I keep getting Segmentation fault: 11. I think I've narrowed it down to the problem being just in the linked list creation -- I marked it as the problem area. C的新手,但是我试图编写此链表程序,并且不断遇到细分错误:11.我认为我已将其范围缩小到仅在链表创建中的问题-我将其标记为问题区域。 When I comment this section out, the seg fault doesn't happen. 当我将本节注释掉时,不会发生段错误。

I keep going over what is happening on paper and I can't understand why it won't work. 我一直在研究纸上正在发生的事情,但我不明白为什么它不起作用。 Perhaps I just misunderstand the use of pointers or malloc since I'm inexperienced. 也许由于我没有经验,所以我只是误解了指针或malloc的使用。

example text file that this program should work with: 该程序应使用的示例文本文件:

>984932:39284 mus musculus okodvcxvmkw2e2p \n
ATCTCAATCGCACTATCTAGCATGTCGTATGCTTGCATGTCGTAGTCGT\n
ATGCTATGCTTACTCTATTTACGGCGCATCGTGATCGTAGGAGCGAGCT\n

>984932:39284 mus huumoros okodvcxvmkw2e2p \n
ATCTCAATCGCACTATCTAGCATGTCGTATGCTTGCATGTCGTAGTCGT\n
ATGCTATGCTTACTCTATTTACGGCGCATCGTGATCGTAGGAGCGAGCT\n

>984932:39284 mus pisces okodvcxvmkw2e2p \n
ATCTCAATCGCACTATCTAGCATGTCGTATGCTTGCATGTCGTAGTCGT\n
ATGCTATGCTTACTCTATTTACGGCGCATCGTGATCGTAGGAGCGAGCT\n

What I'm trying to do: Create a linked list, where each node is one block of the text above. 我想做的是:创建一个链表,其中每个节点都是上面文本的一个块。 That is, each node contains the header which starts with '>', and the sequence data that is all of the ACTG. 也就是说,每个节点都包含以“>”开头的标头,以及所有ACTG的序列数据。 In the above example text file, there would be 3 nodes in addition to the head/tail nodes in the list. 在上面的示例文本文件中,列表中的头/尾节点之外还有3个节点。

How I'm trying to do it (the problem section): Char is scanned. 我要怎么做(问题部分):扫描了Char。 If char is '>', then we know we're at the header, and we read all following chars into the new node's header field until we reach the newline char. 如果char是'>',那么我们知道我们在标题处,并且我们将所有随后的char读取到新节点的header字段中,直到到达换行符char为止。 At this point, we know we're going to read in sequence data. 至此,我们知道我们将按顺序读取数据。 Continue to do so until we reach another '>', and when we do, repeat. 继续这样做,直到到达另一个'>',然后重复一次。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int list_header_size = 200;
int list_data_size = 2000;

struct list{
    char *header;
    char *data;
    struct list *next;
    struct list *prev;
};

//append char onto a string
void append(char *s, char c){
    int len = strlen(s);
    s[len] = c;
    s[len + 1] = '\0';
}

int create_list(char *filename){

    FILE *fp = fopen(filename, "r");

    if(fp == NULL){
        printf("File could not be opened. Exiting..");
        exit(1);
    }

    //setup head - doesn't hold a char
    struct list *head = malloc(sizeof(struct list));
    head->next = NULL;
    head->header = NULL;
    head->data = NULL;
    head->prev = NULL;

    //setup tail - doesn't hold a char
    struct list *tail = malloc(sizeof(struct list));
    tail->next = NULL;
    tail->header = NULL;
    tail->data = NULL;
    tail->prev = NULL;

    /***scan the .fasta file, populate list***/

    //char holder
    char c;
    int list_size = 0;
    int i = 1;

    //pull single char from file until end of file is reached
    do{

        c = getc(fp);

        //******PROBLEM IS IN THIS SECTION********//

        //if header text is found
        if(c == '>'){

            //create a node
            struct list *temp = malloc(sizeof(struct list));

            //first case to setup head
            if(i == 1){
                head->next = temp;
                temp->prev = head;
                i = 0;
            }

            tail->next = temp;
            tail->prev = temp;

            //create space for header/sequence data in the new node
            temp->header = (char*) malloc(sizeof(list_header_size));
            temp->data = (char*) malloc(sizeof(list_sequence_size));

            //add current char to header
            append(temp->header, c);

            c = getc(fp);

            //put file's header data into node's header data
            while(c != '\n'){
                append(temp->header, c);

                c = getc(fp);
            }

            //put file's sequence data into node's sequence data
            while(c != '>' && c != EOF){
                append(temp->data, c);
            }
        }

        //*******END OF PROBLEM SECTION********//

    }while(c != EOF);

    /***end of scanning .fasta file and creating linked list***/

    return 1;
}

int main(int argc, char * argv[]){

    char *filename = (char*) malloc(80);

    //check options
    int i;
    for(i = 1; i < argc; i++){

        if(argv[i][0] == '-'){

            switch(argv[i][1]){     
                default:;
            }

        }else{
            //arg is filename
            filename = argv[i];
        }

    }

    create_list(filename);

    return 1;
}

The most immediate thing is this: 最直接的事情是这样的:

  //create space for header/sequence data in the new node
  temp->header = (char*) malloc(sizeof(list_header_size));
  temp->data = (char*) malloc(sizeof(list_sequence_size));

Which I believe should be this: 我认为应该是这样的:

  //create space for header/sequence data in the new node
  temp->header = malloc(list_header_size);
  temp->data = malloc(list_sequence_size);

if you're super - new to C there are probably other things here too, but mallocs and their sizes are always the first things I check, and this one isn't right. 如果您是超级用户-还是C语言新手,那么这里可能还有其他事情,但是mallocs及其大小始终是我检查的第一件事,而这是不对的。

EDIT Another Problem: 编辑另一个问题:

Your buffers are now allocated, but your append() function expects them to be zero-terminated from inception. 现在已经分配了缓冲区,但是您的append()函数期望它们从开始就以零终止。 They are not. 他们不是。 Add this: 添加:

  temp->header = malloc(list_header_size);
  temp->data = malloc(list_sequence_size);
  temp->header[0] = temp->data[0] = 0; // <=== this

To be honest, since these sizes are fixed I would have rather you just declare the actual node structure like this: 老实说,由于这些大小是固定的,我宁愿您只声明实际的节点结构,如下所示:

struct list{
    char header[200];
    char data[2000];
    struct list *next;
    struct list *prev;
};

and avoid all the extra allocations entirely, just allocating nodes and not their fields. 并完全避免所有额外分配,仅分配节点而不分配其字段。 If the field sizes ever become dynamic, this would need to change, but until then, keep it simple. 如果字段大小变为动态,则需要进行更改,但是在此之前,请保持简单。

I would have a look at your append(...) function, and the data you feed into it. 我将看看您的append(...)函数以及您向其中提供的数据。 Your first call to the function is 您对该函数的第一个调用是

append(temp->header, c);

and temp->header is not guaranteed to be zeroed. 并且不能保证temp->header为零。 It could point to anything, though most compilers will zero it (or attempt to do so). 它可以指向任何东西,尽管大多数编译器会将它归零(或尝试这样做)。 Use calloc instead of malloc . 使用calloc而不是malloc

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM