Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
fclose()导致分段错误_C_Segmentation Fault_Fopen_Fclose - Fatal编程技术网

fclose()导致分段错误

fclose()导致分段错误,c,segmentation-fault,fopen,fclose,C,Segmentation Fault,Fopen,Fclose,我正在解析一个以制表符分隔的文本文件。其第一列包含格式为chrX的字符串,其中X表示一组字符串,例如,“1”、“2”、…、“X”、“Y” 当解析文件时,它们都存储在名为染色体的char*中 文本文件按字典顺序排列在第一列,即,我将有许多行,从“chr1”开始,然后是“chr2”,等等 在每个“chrX”条目中,我需要打开与此条目关联的另一个文件: FILE *merbaseIn; // loop through rows... if (chromosome == NULL)

我正在解析一个以制表符分隔的文本文件。其第一列包含格式为
chrX
的字符串,其中
X
表示一组字符串,例如,“1”、“2”、…、“X”、“Y”

当解析文件时,它们都存储在名为
染色体
char*

文本文件按字典顺序排列在第一列,即,我将有许多行,从“chr1”开始,然后是“chr2”,等等

在每个“chrX”条目中,我需要打开与此条目关联的另一个文件:

FILE *merbaseIn;

// loop through rows...

if (chromosome == NULL)                                                                                                                                                   
    openSourceFile(&chromosome, fieldArray[i], &merbaseIn, GENPATHIN);                                                                                                      
else {                                                                                                                                                                    
    if (strcmp(chromosome, fieldArray[i]) != 0) { // new chromosome                                                                                                   
        fclose(merbaseIn); // close old chromosome FILE ptr                                                                                                                                                                                                                                    
        free(chromosome); // free old chromosome ptr                                                                                                                          
        openSourceFile(&chromosome, fieldArray[i], &merbaseIn, GENPATHIN); // set up new chromosome FILE ptr                                                                  
    }                                                                                                                                                                       
}  
// parse row
我有一个函数
openSourceFile
,其定义如下:

void openSourceFile (char** chrome, const char* field, FILE** filePtr, const char *path) {
    char filename[100];                                                                                                                                                           
    *chrome = (char *) malloc ((size_t) strlen(field));
    if (*chrome == NULL) {                                                                                                                                                        
        fprintf(stderr, "ERROR: Cannot allocate memory for chromosome name!");                                                                                                      
        exit(EXIT_FAILURE);                                                                                                                                                         
    }                                                                                                                                                                             

    strcpy(*chrome, field);                                                                                                                                                       
    sprintf(filename,"%s%s.fa", path, field);                                                                                                                                     

    *filePtr = fopen(filename, "r");                                                                                                                                              
    if (*filePtr == NULL) {                                                                                                                                                       
        fprintf(stderr, "ERROR: Could not open fasta source file %s\n", filename);                                                                                                  
        exit(EXIT_FAILURE);                                                                                                                                                         
    }                                                                                                                                                                             
}      
问题是,我的应用程序退出时,在下一行出现了从第一条染色体到第二条染色体的分段错误(从
chr1
chr2
),我关闭了打开的第一个染色体文件:

fclose(merbaseIn);
我知道我没有传递
fclose
空指针,因为在出现分段错误之前,我一直在从该文件读取数据。我甚至可以把它包装成一个条件,但我仍然会犯错误:

if (merbaseIn != NULL) {
    fclose(merbaseIn);
}
此外,我知道
openSourceFile
是有效的(至少对于
chr1
,在设置
file*
的第一个文件句柄时是有效的),因为我的应用程序解析
chr1
行并正确读取
file*
源文件中的数据


这个
fclose
调用导致出现分段错误的原因是什么?

我注意到的一个错误是这一行:

 *chrome = (char *) malloc ((size_t) strlen(field));
应该是:

 *chrome = (char *) malloc ((size_t) strlen(field)+1);
这是因为字符串末尾有一个结束符0,您还必须为它腾出空间

valgrind --db-attach=yes --leak-check=yes --tool=memcheck --num-callers=16 --leak-resolution=high ./yourprogram args
segfault很可能是由堆上的内存损坏引起的,而不是影响本地的任何东西。将立即显示您的第一次错误访问

编辑:自2014年3.10.0版以来,
--db attach
选项已被弃用到
valgrind
。发行说明指出:

The built-in GDB server capabilities are superior and should be used
instead. Learn more here:
The built-in GDB server capabilities are superior and should be used
instead. Learn more here:

最好的猜测是,代码的其他部分通过缓冲区溢出或类似的错误而损坏内存

虽然不太可能是原因,但当完整文件名超过100个字符时,文件名数组中可能存在溢出情况

我建议使用调试器来监视merbaseIn变量使用的内存位置的更改。

通用指针问题 C语言是一门伟大的语言,但它确实要求你不要破坏自己的记忆。除了前面提到的malloc短1字节的问题外,您可能还有其他指针问题


我建议。在过去,它很受欢迎,但现在我。还有很多其他选择。

除了发现的错误,我怀疑:

free(chromosome);
随后应:

chromosome = NULL;

为了防止使用不再有效的值。

如果只有这个文件*文件ptr就足够了,为什么要使用这个文件**filePtr?
只是一个想法…

valgrind
memcheck
绝对是发现分段故障原因的正确工具。要将调试器与
valgrind
一起使用,请注意,
--db attach
选项到
valgrind
自2014年发布valgrind 3.10.0以来已被弃用。发行说明指出:

The built-in GDB server capabilities are superior and should be used
instead. Learn more here:
The built-in GDB server capabilities are superior and should be used
instead. Learn more here:

查看您使用的每个地方“malloc”,看看您是否犯了错误

例如,我将从文件中读取的行放入一个char**,但我没有正确地输入 将其命名为:

my_list = malloc(sizeof(char) * num_lines_found_in_file);
当它应该是:

my_list = malloc(sizeof(char*)* num_lines_found_in_file);

是,但是strlen()返回size\u t,所以请删除该类型。malloc()返回void*,它可以转换为C中的任何其他(数据)指针类型,因此也可以删除该转换。在这种情况下,可以使用strdup()替换malloc()+strcpy()。我不同意(char*)转换,该转换清楚地说明了意图。我没有在双指针中的指针上运行
free
。我也没有在其他地方释放指针。我废弃了这个应用程序,从头开始编写,一边运行
valgrind
,以确保正确管理内存。谢谢你给我指点这个工具!是的,valgrind教会了我:1)每个人都是对的,我应该只使用smart(自动/参考计数等)指针或垃圾收集;2)valgrind实际上不需要垃圾收集。唯一的警告是测试覆盖率。我认为使用valgrind查找内存泄漏比使用我熟悉的任何GC语言工具(如JVM或.NET语言)都要容易。关闭时使用双文件指针是一种很好的做法。通过这种方式,您可以在关闭原始文件指针后将其设置为
NULL
,因为它不是函数参数。