对fgets的错误...有时候

时间:2012-03-27 13:36:12

标签: c segmentation-fault fgets

我从fgets获得了细分,但有时只是。这是别人的代码,我不懂makefile,所以我用printf语句进行调试......我把它放在main函数的两个部分:(我只创建变量* f和line一次,但是我两次fopen和fclose文件。)

FILE *f = NULL;
char line[1000];
if ((f=fopen(filename,"r+"))==NULL)
{
     printf("Error opening file\n");
     f=0;//...handle error... //(usually just call abort() or return -1
}
//f = rfopen(fname, "r+");
printf("f from eval_args: %d, filename %s\n",f,filename);
printf("trying to read from file...\n");
printf("%s\n",fgets(line, sizeof (line), f));
printf("...succeeded\n");
fclose(f);

给了我两个不同的输出:

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)

我检查文件是否正确打开,并防止读取比'line'更多的字符。我在一个论坛中看到文件名长度不应超过49个字符...但是a)这是一个奇怪的限制,b)为什么它第一次起作用?

有谁知道我还能检查什么?

3 个答案:

答案 0 :(得分:1)

如果不是很麻烦你可以,但猜猜你知道,做点什么;

可以美化一下,但是

#include <stdio.h>
#include <stdarg.h>

#define MAX_LINE    1024

void dbg_fprnt(FILE *fh, char *fmt, ...)
{
    char buf[MAX_LINE];
    char inf[MAX_LINE] = {0};
    va_list args;

    if (fmt && *fmt) {
        va_start(args, fmt);
        va_end(args);
        vsprintf(inf, fmt, args);
    }

    buf[0] = '\n';
    buf[1] = '\0';
    if (ferror(fh)) {
        fprintf(stderr, " * ERR, ferror() --- \n");
    } else if (fh == NULL) {
        fprintf(stderr,
            " * DBG PRNT ERR;; Trying to print from NULL ---\n");
    /* else if (and so forth) */
    } else {
        if (fgets(buf, MAX_LINE, fh) == NULL) {
            perror(" * ERR DBG PRNTF FGETS, --");
        }
    }
    printf("%-15s FC:: %s", inf, buf);
}

int main(void)
{
    char *fn = "lorem_ipsum";
    FILE *fh;

    if ((fh = fopen(fn, "r")) == NULL) {
        fprintf(stderr,
            "Unable to open '%s' for read.\n",
            fn);
        return 1;
    }

    setbuf(stdout, NULL);

    dbg_fprnt(fh, "SOME LINE: %d", 123);
    dbg_fprnt(fh, "%s", "SASA");
    dbg_fprnt(fh, "");
    dbg_fprnt(fh, NULL);
    dbg_fprnt(fh, "%s %d !", "Woot", 33);
    dbg_fprnt(fh, "@%d :::", __LINE__);
    fclose(fh);
    dbg_fprnt(fh, "@%d :::", __LINE__);


    return 0;
}

示例输出:

./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:: 

答案 1 :(得分:0)

根据您的描述,可能的原因可能是第二个fgets没有成功,因此返回NULL,这会导致段错误。那么为什么第二个fgets会失败?你可以看一下......

参考fgets规范:

  
    

成功时,该函数返回相同的str参数。     如果遇到文件结尾且未读取任何字符,则str的内容保持不变,并返回空指针。     如果发生错误,则返回空指针。     使用ferror或feof检查是否发生错误或是否已达到文件结尾。     http://www.cplusplus.com/reference/clibrary/cstdio/fgets/

  

因此,通常直接使用fgets的返回值不是一个好习惯。

答案 2 :(得分:0)

从你的打印出来:

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”,我认为您没有运行相同的代码。< / p>

并且对于注释“//...handle error ... //(通常只是调用abort()或返回-1”,没有代码可以处理它,所以它仍然可以下去并且coredump。< / p>

从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");