3

Is it possible to get HANDLE referring to standard error output that could be written with WriteFile on Windows?

The reason I am asking is that I am writing some logging utilities for me. And I am trying to give the data directly to system to:

  • avoid any potential problems with things not being flushed and
  • let the system interleave messages from separate threads without need for locking (if that actually works is the other question).

The application is otherwise windows subsystem, so it should only write anywhere if the application actually inherited standard error? If that's possible, that is.

NOTE: I already have log sink to OutputDebugString. And it's equivalents for several other platforms. And to file, which uses low-level API to avoid any additional buffering (as the message is already assembled in on-stack buffer and needs to be flushed immediately). And I just want to reuse the code for writing file for writing on standard error too.

Jan Hudec
  • 73,652
  • 13
  • 125
  • 172
  • for the sake of portability, I'd recommend using `fprintf(stderr, ...)`. Using the windows library for stuff that can be done with standard c/c++ is evil. – Andreas Grapentin Jan 07 '13 at 13:15
  • 1
    @AndreasGrapentin, Would `std::cerr` not work then? – chris Jan 07 '13 at 13:16
  • @chris std::cerr is portable c++, so why shouldn't it work? – Andreas Grapentin Jan 07 '13 at 13:17
  • 1
    @AndreasGrapentin, I'm just saying I find it a more preferable solution than C. – chris Jan 07 '13 at 13:18
  • @chris Oh, allright then :) I consider myself more of a C guy, but since the question is tagged C++, `std::cerr` should be preferred over `fprintf(stderr, ...)` – Andreas Grapentin Jan 07 '13 at 13:24
  • It isn't really wise to use non-portable system specific code, especially in non-perfomance-critical sections (if it was performance-critical, it would have no logging at all, obviously). Using iostream is a much better way to do it. – Bartek Banachewicz Jan 07 '13 at 13:50
  • @bartek @andreas: In general I am all for portable code. But in this specific case I already have a bunch of non-portable outputs (OutputDebugString, __android_log_printf, etc.) and it's just a virtual method that will already have the message mostly formatted. Using `boost::format`. So I prefer low level API, especially if it will work without additional locks that would be required around standard library stuff. – Jan Hudec Jan 07 '13 at 14:12

2 Answers2

9

Use GetStdHandle with STD_ERROR_HANDLE.

HANDLE stderr = GetStdHandle(STD_ERROR_HANDLE);
WriteFile(stderr, /*...*/);
avakar
  • 32,009
  • 9
  • 68
  • 103
-1

stderr is not Windows native and is not open until the process initialize C runtime library subsystem(?).

WriteFile is chosen because it is lowest level API for writing but WriteFile could broke internal consistency of stderr, which is evidently without proper locking.

For debugging/tracing purpose, Windows SDK provide OutputDebugString API. Many Windows programmers use this API and DebugView for development.

For general logging, Write an Event to the Event viewer would be more useful.

My recommendation is the VC++ CRTDBG library (link). Its really good!

Community
  • 1
  • 1
9dan
  • 4,222
  • 2
  • 29
  • 44
  • What do you mean "which is evidently without proper locking"? Do you have any reference? I understand what mixing buffered IO via `stderr`, buffered IO via `std::cerr` and unbuffered IO will do and I don't intend to mix them. But that's not a locking issue; it's simply that the buffers obviously don't know about the unbuffered IO bypassing it. That's not interesting. The only thing that is interesting is whether the kernel will make sure the individual system calls are processed atomically or not. – Jan Hudec Jan 07 '13 at 14:18
  • As for CRTDBG, I already have that log sink. And the file log sink, of course. – Jan Hudec Jan 07 '13 at 14:21
  • WriteFile not made for `stderr` handle. You can look at the CRT source code if you have VC++ (Pro) installation. Use if you will, at your own risk. – 9dan Jan 07 '13 at 15:50
  • For atomic I/O, buffering is no concern at all. You must investigate the multithread safety of the library/subsystem/OS implementation, if you are not going to stick to single thread only model. For VC++, it provide thread safe version of C runtime library since decade ago but it is only library-wise safety and nothing is guarantee for the handle access by WriteFile or any other low level I/O methods. – 9dan Jan 07 '13 at 16:00
  • The kernel must handle access by WriteFile and all other low level I/O methods for sake of it's own sanity. – Jan Hudec Jan 08 '13 at 07:25