简体   繁体   English

使用 vfwprintf 时,Valgrind 报告“仍然可以访问”字节

[英]Valgrind reports “still reachable” bytes when using vfwprintf

I am writing two functions as handy shortcuts for printing to stderr : one I am calling eprintf for printing regular strings;我正在编写两个函数作为打印到stderr的便捷快捷方式:一个我调用eprintf来打印常规字符串; and ewprintf for printing wide-character strings.ewprintf用于打印宽字符串。 I have written eprintf as follows:我写eprintf如下:

int eprintf(const char* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    int written = vfprintf(stderr, fmt, args);
    va_end(args);
    return written;
}

ewprintf is the same except that its fmt parameter is of type const wchar_t* and I use vfwprintf to write to stderr . ewprintf是相同的,只是它的fmt参数的类型是const wchar_t*并且我使用vfwprintf写入stderr

I have these two functions declared in a header file called eprintf.h and then defined in eprintf.c .我在名为eprintf.h的 header 文件中声明了这两个函数,然后在eprintf.c中定义。 My main function is simply designed to test these:我的主要 function 旨在测试这些:

#include <stdio.h>
#include <stdlib.h>
#include <locale.h>
#include "eprintf.h"

int main(int argc, char** argv) {
    setlocale(LC_ALL, "");
    ewprintf(L"This is a test.\n");
    return 0;
}

I replaced ewprintf with eprintf and then tested the program with valgrind and had no issues--there were an equal number of allocs to frees, with no bytes labeled as "still reachable";我用ewprintf替换了eprintf ,然后用 valgrind 测试了程序,没有任何问题——有相同数量的分配给释放,没有标记为“仍然可访问”的字节; however, when using ewprintf --which calls vfwprintf --valgrind reports that 5120 bytes in two blocks are "still reachable," with 33 allocs but only 31 frees.但是,当使用ewprintf calls vfwprintf --valgrind 报告两个块中的 5120 字节“仍然可以访问”时,有 33 个分配,但只有 31 个释放。 Running a more detailed leak check to find the cause of the "still reachable" memory, valgrind provides a trace that includes vfwprintf .运行更详细的泄漏检查以查找“仍可访问”memory 的原因,valgrind 提供了包含vfwprintf的跟踪。

I have also tried defining eprintf and ewprintf as variadic macros just like those seen here .我还尝试将eprintfewprintf定义为可变参数宏,就像这里看到的那样。 But, I ran into the same issue with ewprintf written as a macro.但是,我在将ewprintf编写为宏时遇到了同样的问题。

So, my first question: in this case, is this "still reachable" issue actually something to be concerned with?所以,我的第一个问题:在这种情况下,这个“仍然可以解决”的问题实际上是值得关注的吗? Note that valgrind does not report any bytes as "definitely lost," "indirectly lost," or "possibly lost."请注意,valgrind 不会将任何字节报告为“肯定丢失”、“间接丢失”或“可能丢失”。 Second, even if this is not actually a problem per se, is there anything I can do to fix it?其次,即使这本身实际上不是问题,我能做些什么来解决它吗?

Update: here is my implementation for ewprintf for further clarification:更新:这是我对ewprintf的实现,以进一步澄清:

// Notice that its parameter is a wide-character string, and it calls `vfwprintf`.
int ewprintf(const wchar_t* fmt, ...) {
    va_list args;
    va_start(args, fmt);
    int written = vfwprintf(stderr, fmt, args);
    va_end(args);
    return written;
}

Short Answer:简短的回答:

Buffers are associated with stderr .缓冲区与stderr相关联。 Possible to get rid of the message by explicit closing(stderr) before exit, but see note below.可以在退出前通过显式closing(stderr)来消除该消息,但请参阅下面的注释。

Long Answer:长答案:

According to valgrind, the 'still reachable' memory was allocated from buffered writes for vfwprintf.根据 valgrind 的说法,“仍然可以访问”的 memory 是从 vfwprintf 的缓冲写入中分配的。 Those are buffered that are associated with stderr, and are allocated on the first call.那些与 stderr 关联的缓冲,并在第一次调用时分配。

The buffers are automatically closed when stderr is closed.当 stderr 关闭时,缓冲区会自动关闭。 Usually, this is done just before the program exit.通常,这是在程序退出之前完成的。 Looks like valgrind reporting hooks are executed before the final exit.看起来 valgrind 报告挂钩是在final退出之前执行的。 Possible to get rid of this message by explicitly closing stderr in main .可以通过在main中显式关闭 stderr 来消除此消息。 See below.见下文。

While possible to use this option, I think that it's better to leave stderr open, just in case something will need to be shown during program exit (eg, atexit , or other cleanup functions).虽然可以使用此选项,但我认为最好让 stderr 保持打开状态,以防在程序退出期间需要显示某些内容(例如atexit或其他清理功能)。 Code that will attempt to access stderr, will crash the program without any useful message to help debug.尝试访问 stderr 的代码将在没有任何有用的消息帮助调试的情况下使程序崩溃。

Edit 1:编辑1:

According to valgrind documentation ( http://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq ) possible to use the macro RUNNING_ON_VALGRIND to detect if running under valgrind, potentially closing stderr only on this condition.根据 valgrind 文档( http://valgrind.org/docs/manual/manual-core-adv.html#manual-core-adv.clientreq )可以使用宏 RUNNING_ON_VALGRIND 来检测是否在 valgrind 下运行,可能仅关闭 stderr在这种情况下。 disclaimer: I do not have any actual experience using this macro, use with care.免责声明:我没有使用此宏的任何实际经验,请谨慎使用。

int main(int argc, char** argv) {
    setlocale(LC_ALL, "");
    ewprintf(L"This is a test.\n");
    fclose(stderr) ;
    return 0;
}
valgrind --leak-check=full --show-leak-kinds=all ./a.out

==38349== Memcheck, a memory error detector
==38349== Command: ./a.out
==38349== 
This is a test.
==38349== 
==38349== HEAP SUMMARY:
==38349==     in use at exit: 5,120 bytes in 2 blocks
==38349==   total heap usage: 32 allocs, 30 frees, 9,500 bytes allocated
==38349== 
==38349== 1,024 bytes in 1 blocks are still reachable in loss record 1 of 2
==38349==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==38349==    by 0x4EBA18B: _IO_file_doallocate (filedoalloc.c:101)
==38349==    by 0x4EBB88C: _IO_wfile_doallocate (wfiledoalloc.c:70)
==38349==    by 0x4ECA378: _IO_doallocbuf (genops.c:365)
...
==38349==    by 0x4EA7089: buffered_vfprintf (vfprintf.c:2343)
==38349==    by 0x4EA40FD: vfwprintf (vfprintf.c:1301)
==38349==    by 0x1087F1: ewprintf (in /home/owner/Projects/SO/58904606/a.out)
==38349==    by 0x108847: main (in /home/owner/Projects/SO/58904606/a.out)
==38349== 
==38349== 4,096 bytes in 1 blocks are still reachable in loss record 2 of 2
==38349==    at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==38349==    by 0x4EBB858: _IO_wfile_doallocate (wfiledoalloc.c:79)
==38349==    by 0x4ECA378: _IO_doallocbuf (genops.c:365)
...
==38349==    by 0x4EA7089: buffered_vfprintf (vfprintf.c:2343)
==38349==    by 0x4EA40FD: vfwprintf (vfprintf.c:1301)
==38349==    by 0x1087F1: ewprintf (in /home/owner/Projects/SO/58904606/a.out)
==38349==    by 0x108847: main (in /home/owner/Projects/SO/58904606/a.out)
==38349== 
==38349== LEAK SUMMARY:
==38349==    definitely lost: 0 bytes in 0 blocks
==38349==    indirectly lost: 0 bytes in 0 blocks
==38349==      possibly lost: 0 bytes in 0 blocks
==38349==    still reachable: 5,120 bytes in 2 blocks
==38349==         suppressed: 0 bytes in 0 blocks
==38349== 
==38349== For counts of detected and suppressed errors, rerun with: -v
==38349== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM