C FGET上的segfault。。。有时

C FGET上的segfault。。。有时,c,segmentation-fault,fgets,C,Segmentation Fault,Fgets,我从FGET中得到了一个分段,但只是有时候。这是其他人的代码,我不理解makefile,所以我正在调试printf语句。。。我把它放在主函数的两个部分:(我只创建了一次变量*f和line,但我两次都打开和丢失了文件。) 这给了我两种不同的输出: f from eval_args: 4609600, filename /correct/path/to/file trying to read from file... 100 ...succeeded f prior to entering d

我从FGET中得到了一个分段,但只是有时候。这是其他人的代码,我不理解makefile,所以我正在调试printf语句。。。我把它放在主函数的两个部分:(我只创建了一次变量*f和line,但我两次都打开和丢失了文件。)

这给了我两种不同的输出:

f from eval_args: 4609600, filename /correct/path/to/file
trying to read from file...
 100

...succeeded

f prior to entering density profile: 4609600, filename /correct/path/to/file
trying to read from file...
Segmentation fault (core dumped)
我检查文件是否正确打开,并防止读取的字符超过“行”中的字符数。我在一个论坛上看到文件名长度不应该超过49个字符。。。但是a)这是一个奇怪的限制,b)为什么它第一次起作用


有人知道我还可以检查什么吗?

根据您的描述,可能的原因可能是第二个
fgets
没有成功,因此它返回
NULL
,这导致了段故障。那么为什么第二个
fgets
失败?你可以看看

参考《联邦法规》和《联邦法规》的规定:

成功时,函数返回相同的str参数。 如果遇到文件结尾且未读取任何字符,则str的内容保持不变,并返回空指针。 如果发生错误,将返回空指针。 使用ferror或feof检查是否发生错误或是否到达文件末尾。


因此,通常直接使用
fgets

的返回值不是一个好的做法,如果这不是一个很麻烦的问题,但是你猜你知道,做一些类似的事情

可以稍微美化一下,但是:

从您的打印输出:

f from eval_args: 4609600, filename /correct/path/to/file
trying to read from file...
 100

...succeeded

f prior to entering density profile: 4609600, filename /correct/path/to/file
trying to read from file...
Segmentation fault (core dumped)
您使用的是“输入密度配置文件之前的f”,而不是“来自eval_args的f”,但是“输入密度配置文件之前的f”在您提供的源代码中不存在,我认为您运行的代码不同

对于注释“/…handle error…”/(通常只调用abort()或返回-1)“没有代码来处理它,因此它仍然可以继续运行并进行coredump

根据fgets返回的说明:

成功完成后,fgets()应返回s。如果流位于文件结尾,则应设置流的文件结尾指示符,fgets()应返回空指针。如果发生读取错误,则应设置流的错误指示符,fgets()应返回空指针,并应设置errno以指示错误

所以EOF或任何不好的东西都会导致printf coredump

我的建议大致如下:

    FILE *f = fopen(filename,"r+");
    if (f) {
        char line[1000];
        printf("f from eval_args: %p, filename %s\n",f,filename);
        printf("trying to read from file...\n");
        while(fgets(line, sizeof (line), f)) printf("%s",line);
        fclose(f);
    }
    else printf("Error opening file\n");

不打印()打印
(空)
遇到空字符串时?你能发布一个小的可编译程序来重现这个问题吗?首先你应该把
fgets
作为一个单独的语句,然后你应该使用调试器来帮助你定位和检查错误。感谢@Joachim的建议,我把fgets放在它自己的行上,segfault就是definitely在那里。现在我要弄清楚为什么那个低级函数会为相同的输入提供不可复制的行为…@H2CO3,从谷歌的快速搜索来看,它似乎没有很好的定义,但对我来说,printf(“%s\n”,NULL)也会导致segfault,因此我以前可能有两个问题。感谢您的提示,我现在将fgets和printf调用放在单独的行中,而且fgets函数似乎根本不会返回(segfault甚至在它给出NULL输出之前)@craq-在调用
fgets
之前,确保您没有无意中关闭或覆盖文件句柄
f
。@John-故意关闭、覆盖并再次打开应该可以,对吧?哇,谢谢,我确实学到了一些东西。我得到的输出与您略有不同,但这可能并不重要。特别是因为它不适用于fgets。对我来说,输出的最后3行看起来像:
@62:::FC::proident,sunt in culpa qui officia desunt mollit anim id est labourum.
*ERR DBG PRNTF fgets,-:错误的文件号
@64::FC:
@craq:
\uu-LINE\uuu\uuuuuu>
dbg\u fprnt(fh)”@%d:::”,\uuuuu LINE\uuuuuuu);
”在第52行,在你的文件中,它在第62行。是的,我更改了字符串输出,这样我就可以很容易地知道输出来自哪里。是的,不处理错误是懒惰的,但如果是这样的话,我至少会知道,因为printf语句。只是重申一下,是fgets调用,而不是printf生成segfault。我现在知道了ve
char*dummy;dummy=fgets(line,sizeof(line)-1,f);printf(“fgets已返回\n”);…
并且在打印该行之前发生segfault。
./fe
SOME LINE: 123  FC:: Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod 
SASA            FC:: tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam,
                FC:: quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo 
                FC:: consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse 
Woot 33 !       FC:: cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non 
@52 :::         FC:: proident, sunt in culpa qui officia deserunt mollit anim id est laborum.
 * ERR DBG PRNTF FGETS, --: Bad file descriptor
@54 :::         FC:: 
f from eval_args: 4609600, filename /correct/path/to/file
trying to read from file...
 100

...succeeded

f prior to entering density profile: 4609600, filename /correct/path/to/file
trying to read from file...
Segmentation fault (core dumped)
    FILE *f = fopen(filename,"r+");
    if (f) {
        char line[1000];
        printf("f from eval_args: %p, filename %s\n",f,filename);
        printf("trying to read from file...\n");
        while(fgets(line, sizeof (line), f)) printf("%s",line);
        fclose(f);
    }
    else printf("Error opening file\n");