fclose() 导致分段错误

发布于 2024-08-04 22:21:38 字数 4792 浏览 5 评论 0原文

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

在解析文件时,它们均存储在名为 chromosomechar* 中。

文本文件按字典顺序在第一列排序,即,我将有许多行以“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 一个 NULL 指针,因为直到分段错误,我正在从此文件中读取数据。我什至可以将其包装在条件中,但仍然遇到错误:

if (merbaseIn != NULL) {
    fclose(merbaseIn);
}

此外,我知道 openSourceFile 可以工作(至少对于 chr1 来说,当设置 < 的第一个文件句柄时) code>FILE*),因为我的应用程序解析 chr1 行并正确从 FILE* 源文件读取数据。

这个 fclose 调用是什么导致了分段错误的发生?

I have a tab-delimited text file that I am parsing. Its first column contains strings of the format chrX, where X denotes a set of strings, e.g., "1", "2", ..., "X", "Y".

These are each stored in a char* called chromosome, as the file is parsed.

The text file is sorted on the first column lexicographically, i.e., I will have a number of rows starting with "chr1", and then "chr2", etc.

At each "chrX" entry, I need to open another file that is associated with this entry:

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

I have the function openSourceFile that is defined as follows:

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);                                                                                                                                                         
    }                                                                                                                                                                             
}      

The problem is that my application quits with a Segmentation Fault going from the first chromosome to the second (from chr1 to chr2) at the following line, where I close the first chromosome file that I opened:

fclose(merbaseIn);

I know I'm not passing fclose a NULL pointer, because up until the Segmentation Fault, I am reading data from this file. I can even wrap this in a conditional and I still get the Fault:

if (merbaseIn != NULL) {
    fclose(merbaseIn);
}

Further, I know openSourceFile works (at least for chr1, when setting up the first file handle of FILE*) because my application parses chr1 rows and reads data from the FILE* source file correctly.

What is it about this fclose call that is causing a Segmentation Fault to occur?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

墨洒年华 2024-08-11 22:21:38
valgrind --db-attach=yes --leak-check=yes --tool=memcheck --num-callers=16 --leak-resolution=high ./yourprogram args

段错误很可能是由堆上的内存损坏引起的,而不是影响本地的任何东西。 Valgrind 将立即向您显示您进行的第一个错误访问。

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

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

http://valgrind.org/docs/manual/manual-core-adv.html #manual-core-adv.gdbserver

valgrind --db-attach=yes --leak-check=yes --tool=memcheck --num-callers=16 --leak-resolution=high ./yourprogram args

It's very likely the segfault is caused by memory corruption on the heap, not anything that's affecting locals. Valgrind will immediately show you the first wrong access you make.

Edit: The --db-attach option to valgrind has been deprecated since release 3.10.0 in 2014. The release notes state:

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

http://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver

彼岸花ソ最美的依靠 2024-08-11 22:21:38

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

 *chrome = (char *) malloc ((size_t) strlen(field));

应该是:

 *chrome = (char *) malloc ((size_t) strlen(field)+1);

这是因为字符串末尾有一个结束 0,您还必须为它腾出空间

one error i notice is this line:

 *chrome = (char *) malloc ((size_t) strlen(field));

which should be:

 *chrome = (char *) malloc ((size_t) strlen(field)+1);

This is because a string has a closing 0 at the end which you also have to make room for

烟─花易冷 2024-08-11 22:21:38

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

尽管不太可能是原因,但当完整文件名超过 100 个字符时,文件名数组中可能会出现溢出情况。

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

Best guess is that some other part of your code is corrupting memory through a buffer overrun or similar bug.

Although unlikely to be the cause, you have a potential overrun condition in your filename array when the full filename exceeds 100 chars.

I would suggest using a debugger to watch for changes in the memory location used by the merbaseIn variable.

你的心境我的脸 2024-08-11 22:21:38

通用指针问题

C 是一种很棒的语言,但它确实要求您不要破坏自己的内存。除了前面提到的 malloc 短 1 个字节的问题之外,您可能还会遇到其他指针问题。

我建议使用内存调试器。过去,电围栏相当流行,但现在我了解有关 valgrind 的更多信息。还有很多其他选择。

Generic Pointer Problem

C is a great language but it does require that you not clobber your own memory. Besides the problem previously noted where the malloc is 1 byte short, you may have other pointer problems.

I would suggest using a memory debugger. In the past, Electric Fence was rather popular but these days I hear more about valgrind. There are lots of other choices.

魂ガ小子 2024-08-11 22:21:38

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

free(chromosome);

应该遵循:

chromosome = NULL;

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

In addition to error found by reinier, I suspect that:

free(chromosome);

should be followed by:

chromosome = NULL;

in order to prevent potential usage of a no longer valid value.

歌入人心 2024-08-11 22:21:38

如果只有这个 FILE* filePtr 就足够了,为什么还要这个 FILE** filePtr ?
只是一个想法...

why this FILE** filePtr if only this FILE* filePtr would be enough ?
just a thought...

柠檬 2024-08-11 22:21:38

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

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

http:// /valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver

valgrind with memcheck is definitely the right tool to discover the cause of the segmentation fault. To use a debugger with valgrind, note that the --db-attach option to valgrind has been deprecated since Valgrind 3.10.0 was released in 2014. The release notes state:

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

http://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.gdbserver

℉絮湮 2024-08-11 22:21:38

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

例如,我将从文件中读取的行放入 char** 中,但我错误地
将其分配为:

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

当它应该是:

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

Review every place you used "malloc" and see if you made a mistake.

For example, I was putting lines read from a file into a char**, but I incorrectly
malloced it as:

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

When it should have been:

my_list = malloc(sizeof(char*)* num_lines_found_in_file);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文