【问题标题】:fclose doesn't seem to be working in Cfclose 似乎不适用于 C
【发布时间】:2013-01-18 04:47:48
【问题描述】:
    FILE *file = fopen(argv[1], "r");
    if(file != NULL){
        char command[MAX_BUFFER];
        while(fgets(command, MAX_BUFFER, file) != NULL){ //read line
            //operations
        }
        fclose(file);
    }
    else write(fileno(stderr), ERROR_MESSAGE, strlen(ERROR_MESSAGE));

我正在开发一个非常基本的 UNIX shell 实现,它从文件中逐行读取和执行。从上面的代码中,我试图弄清楚为什么 fclose() 可能会失败,因为 valgrind 似乎告诉我我已经打开了这个文件描述符。

我是否正确假设泄漏摘要中的“仍然可达”568 字节以某种方式引用了失败的fclose()

==25428== FILE DESCRIPTORS: 4 open at exit.
==25428== Open file descriptor 3: test
==25428==    at 0x4F186B0: __open_nocancel (syscall-template.S:82)
==25428==    by 0x4EAC628: _IO_file_fopen@@GLIBC_2.2.5 (fileops.c:233)
==25428==    by 0x4EA1265: __fopen_internal (iofopen.c:93)
==25428==    by 0x400C0C: main (in /home/Desktop/sh)
==25428== 
==25428== Open file descriptor 2: /dev/pts/0
==25428==    <inherited from parent>
==25428== 
==25428== Open file descriptor 1: /dev/pts/0
==25428==    <inherited from parent>
==25428== 
==25428== Open file descriptor 0: /dev/pts/0
==25428==    <inherited from parent>
==25428== 
==25428== LEAK SUMMARY:
==25428==    definitely lost: 0 bytes in 0 blocks
==25428==    indirectly lost: 0 bytes in 0 blocks
==25428==      possibly lost: 0 bytes in 0 blocks
==25428==    still reachable: 568 bytes in 1 blocks
==25428==         suppressed: 0 bytes in 0 blocks

【问题讨论】:

  • fclose() 有一个返回值。核实。如果它失败了,那么你可能会破坏堆栈。
  • -g 标志编译会有帮助。
  • 出于好奇,你为什么用write(fileno(stderr), ERROR_MESSAGE, strlen(ERROR_MESSAGE))而不是fputs(ERROR_MESSAGE, stderr)
  • 另外,为什么fileno(stderr) 而不是STDERR_FILENO?除非你在某个地方是 freopen-ing stderr,否则这只会让维护者感到困惑。
  • @KeithThompson 对于这个实现,我将分叉一些进程,如果我没记错的话,fputs 会在内部缓冲类似于 printf 的字符串

标签: c shell unix file-io memory-leaks


【解决方案1】:

对了,检查返回值,也贴上一个错误来简单解释一下。如果您想确认它仍然打开,请尝试 lsof,但您可能需要使用 grep 获取程序名称或 pid,因为可能有几十个。

【讨论】:

    【解决方案2】:

    您的可见代码看起来不错。 但是要回答您的问题:可能,但问题出在其他地方;-)

    要调试您的程序,请注释掉“操作”,这样您就有了一个空循环。 valgrind 还在抱怨吗?

    否:问题很可能出在您命名为“操作”的代码中。

    删除 cmets 并在 (-g) 上使用调试符号进行编译,并将 valgrind 与以下选项一起使用: valgrind --leak-check=yes --show-reachable=yes --track-origins=yes yourprogram

    是的:(非常不可能)其他东西被破坏了,尝试使用更多注释代码进行 valgrind。

    要在编译时查找错误,请使用编译器的标志(例如 gcc 有 -Wall -Wextra -Wwrite-strings -Wformat=2 -Wformat -Wformat-security -D_FORTIFY_SOURCE=2 等)。

    并利用静态分析器,例如llvm/clang(使用 clang --analyze yourprogram.c 编译)

    【讨论】:

      【解决方案3】:

      @rockdaboot 建议注释掉我的操作表明我仍在丢失内存,但至少我知道它不是来自 fclose ......谢谢大家的提示!返回调试!

      【讨论】:

        猜你喜欢
        • 2011-11-10
        • 2020-04-04
        • 2023-04-06
        • 2017-08-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多