录音室过滤器在管道输入时崩溃

时间:2014-12-07 09:04:05

标签: c string stdio

我使用strfry编写了一个用anagram字符串编写的程序。它在默认标准输入时非常有效,但在与stdio重定向(函数,但最后是段错误)一起使用时会崩溃:

#include "stdio.h"
#include "stdlib.h"
#include "string.h"
#include "sys/mman.h"

int main(int argc,char *argv[]) {
    FILE *fryend=stdin;
    if (argc==1) goto mainloop;
    if (argc>1) fryend=fopen(argv[1],"r") ? fryend : stdin;

    mainloop:;
    char *buf=malloc(4096);
    while (!ferror(fryend)) {
        memset(buf,0,4096);
        strfry(fgets(buf,4095,fryend));
        fputs(buf,stdout);
    }
    free(buf);
    if (fryend!=stdin) fclose(fryend);
    return 0;
}

这里有什么问题?使用GNU libc / GCC。运行valgrind并且没有检测到内存泄漏。

3 个答案:

答案 0 :(得分:1)

重写此行

if (argc>1) fryend=fopen(argv[1],"r") ? fryend : stdin;

没有条件运算符。

也许像

if (argc > 1) {
    FILE *tmp = fopen(argv[1], "r");
    if (tmp) fryend = tmp;
}

答案 1 :(得分:0)

重定向stdin

a.out <test.txt

fgets()可能会返回NULL

来自man fgets()

  

返回值

     

[...] fgets()在出错时或在没有读取任何字符的情况下发生文件结束时返回[s] [...] NULL。

反过来NULL传递给strfry()

strfry(fgets(buf, 4095, fryend));

这不是一个好主意。

答案 2 :(得分:0)

当达到文件末尾时,

fgets返回NULL。您应该使用此返回值而不是调用ferrorfeof来控制循环。您还应该注意不要将NULL指针传递给字符串函数。他们可能会优雅地处理这个问题,但通常不会。

所以你的循环应该是这样的:

while (fgets(buf, 4096, fryend)) {
    strfry(buf);
    fputs(buf, stdout);
}

我抛弃了memset,因为fgets的结果是以空值终止的,并且不会溢出缓冲区,所以你可以传递完整的4096字节长度。