C 我创建的二进制文件中的fread()分段错误

C 我创建的二进制文件中的fread()分段错误,c,C,我是python的c新手。我正在尝试编写两个c脚本,一个用于读取FASTA格式的纯文本文件(用于DNA/RNA/蛋白质序列)。他们看起来像这样 >sequence1 ATCTATGTCGCTCGCTCGAGAGCTA >sequence2 CGTCGCTGGGATCGATTTCGATAGCT >sequence3 AAATATAACTCGCTAGCTCGATCGATC >sequence4 CTCTCTCCTCTCTCTATATAGGGG …其中单个序列由“>”字符分隔

我是python的c新手。我正在尝试编写两个c脚本,一个用于读取FASTA格式的纯文本文件(用于DNA/RNA/蛋白质序列)。他们看起来像这样

>sequence1
ATCTATGTCGCTCGCTCGAGAGCTA
>sequence2
CGTCGCTGGGATCGATTTCGATAGCT
>sequence3
AAATATAACTCGCTAGCTCGATCGATC
>sequence4
CTCTCTCCTCTCTCTATATAGGGG
…其中单个序列由“>”字符分隔。在每个序列中,实际序列及其标签由换行符分隔。(即“>标签\n顺序”)。读取纯文本然后将其写入二进制文件的脚本似乎可以工作。然而,当我试图读取二进制文件并打印其内容时,我会遇到一个分段错误(核心转储)

我试图在这里发布一个简化的示例,但这个示例似乎没有错误。因此,我觉得必须将我的全部代码片段附加到这里。我一定错过了什么

下面是第一个脚本,它读入一个纯文本fasta文件,首先用“>”字符拆分,然后用换行符拆分,为上述fasta文件中的每个序列创建“序列”结构。然后将这些结构写入“your_sequences.bin”

我认为错误一定在上面脚本的某个地方(即我的二进制文件被弄乱了),因为分段错误是由下面脚本中的fread()语句引起的。我不认为调用fread()时出错,但也许我错了

#include <stdio.h>
#define BUZZ_SIZE 1024

struct sequence {
    char *sequence;
    char *label; };

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

    struct sequence this_seq;
    int n;
    FILE *fasta_bin;

    fasta_bin = fopen(argv[1],"rb");
    for (n=0;n<4;n++) {
        fread(&this_seq, sizeof(struct sequence), 1, fasta_bin);
        printf (">%s\n%s\n", this_seq.label, this_seq.sequence);
    }

    fclose(fasta_bin);

    return(0); 
在过去的几个小时里,我对这个问题进行了大量的修改。我希望我没有犯一些愚蠢的错误,浪费了你的时间


感谢您的帮助。

您遇到了分段错误,因为在您的程序中,您使用的是指针,而没有为指针分配内存:

        printf (">%s\n%s\n", this_seq.label, this_seq.sequence);
首先需要将内存分配给
this_seq.label
this_seq.sequence
指针,如下所示:

this_seq.sequence = malloc(size_of_sequence);
if (this_seq.sequence == NULL)
   exit(EXIT_FAILURE);

this_seq.label = malloc(size_of_label);
if (this_seq.label == NULL)
   exit(EXIT_FAILURE);
fread(this_seq.sequence, size_of_sequence, 1, fasta_bin);
fread(this_seq.label, size_of_label, 1, fasta_bin);
然后将数据读入其中,如下所示:

this_seq.sequence = malloc(size_of_sequence);
if (this_seq.sequence == NULL)
   exit(EXIT_FAILURE);

this_seq.label = malloc(size_of_label);
if (this_seq.label == NULL)
   exit(EXIT_FAILURE);
fread(this_seq.sequence, size_of_sequence, 1, fasta_bin);
fread(this_seq.label, size_of_label, 1, fasta_bin);

出现分段错误是因为在程序中使用指针时没有为指针分配内存:

        printf (">%s\n%s\n", this_seq.label, this_seq.sequence);
首先需要将内存分配给
this_seq.label
this_seq.sequence
指针,如下所示:

this_seq.sequence = malloc(size_of_sequence);
if (this_seq.sequence == NULL)
   exit(EXIT_FAILURE);

this_seq.label = malloc(size_of_label);
if (this_seq.label == NULL)
   exit(EXIT_FAILURE);
fread(this_seq.sequence, size_of_sequence, 1, fasta_bin);
fread(this_seq.label, size_of_label, 1, fasta_bin);
然后将数据读入其中,如下所示:

this_seq.sequence = malloc(size_of_sequence);
if (this_seq.sequence == NULL)
   exit(EXIT_FAILURE);

this_seq.label = malloc(size_of_label);
if (this_seq.label == NULL)
   exit(EXIT_FAILURE);
fread(this_seq.sequence, size_of_sequence, 1, fasta_bin);
fread(this_seq.label, size_of_label, 1, fasta_bin);
我认为错误一定在上面的脚本中的某个地方(即我的 二进制文件被弄乱了)

有点

因为分段错误是由 下面脚本中的fread()语句

我非常确信,错误不会发生在
fread()
中,而是发生在以下
printf()

我想我没有犯错误 调用fread()时出错,但可能我错了

#include <stdio.h>
#define BUZZ_SIZE 1024

struct sequence {
    char *sequence;
    char *label; };

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

    struct sequence this_seq;
    int n;
    FILE *fasta_bin;

    fasta_bin = fopen(argv[1],"rb");
    for (n=0;n<4;n++) {
        fread(&this_seq, sizeof(struct sequence), 1, fasta_bin);
        printf (">%s\n%s\n", this_seq.label, this_seq.sequence);
    }

    fclose(fasta_bin);

    return(0); 
您的
fread()
对应于
fwrite()
。有充分的理由期待你能准确地读回所写的内容。这里的主要问题对于C新手来说是一个常见的问题:您误解了C字符串(以null结尾的
char
数组)的本质,没有理解数组和指针之间关键但微妙的区别

为了进一步扩展,C没有一级字符串数据类型。相反,标准库提供了对类型为
char
的对象序列进行操作的“字符串”函数,其中序列的结尾由值为0的终止符
char
标记。此类序列通常包含在
char
数组中,并且始终可以将其视为。因为这是标准库所支持的,所以该约定在程序和第三方库中也普遍使用

C、 但是,没有将数组传递给函数或将其作为返回值接收的机制。赋值运算符或大多数其他运算符也不能处理数组,甚至索引运算符
[]
也不行。相反,在大多数上下文中,数组类型的值会自动转换为指向第一个数组元素的指针,这些指针可以传递并用作各种运算符的操作数。看到这一点(部分),缺乏经验的C程序员经常错误地用这样的指针而不是指向数据的指针来识别字符串

当然,指针值只是一个地址。您可以将其复制并存储在程序中的任意位置,但这对指向的数据没有任何作用。现在我终于说到点子上了:你也可以像你的程序那样写出一个指针值并读回,但是这样做很少有用,因为当你这样做的时候,指向的数据不会出现。除非将指针读回编写它的同一进程,否则回读指针值不太可能有效,而且它肯定没有编写它的程序中的意义

您必须改为将指向的数据写入,但必须选择一种格式。特别是,标题和序列通常具有不同的长度,您需要决定的一个关键问题是,如果有的话,二进制格式应该如何反映这一点。不过,如果我可以这么大胆的话,我有一个建议,可以使用一个定义良好的格式:Fasta格式!真的

除了数据压缩之外,您几乎无法更紧凑地表达fasta格式的数据,因为该格式所做的只是表达它所传递的可变长度数据。那么,您需要回答的问题是,您正试图通过重新格式化来实现什么——这既是重新格式化的原因,也是基于此,您的目标格式实际上是什么

我认为错误一定在上面的脚本中的某个地方(即我的 二进制文件被弄乱了)

有点

因为分段错误是由 下面脚本中的fread()语句

我非常确信,错误不会发生在
fread()
中,而是发生在以下
printf()

我想我没有犯错误 调用fread()时出错,但可能我错了

#include <stdio.h>
#define BUZZ_SIZE 1024

struct sequence {
    char *sequence;
    char *label; };

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

    struct sequence this_seq;
    int n;
    FILE *fasta_bin;

    fasta_bin = fopen(argv[1],"rb");
    for (n=0;n<4;n++) {
        fread(&this_seq, sizeof(struct sequence), 1, fasta_bin);
        printf (">%s\n%s\n", this_seq.label, this_seq.sequence);
    }

    fclose(fasta_bin);

    return(0); 
您的
fread()
对应于
fwrite()