How can I call freopen but open the file with shared access instead of exclusive access?

A customer wants to redirect their program's stdout to a file. They followed the sample code which basically boils down to the line

    FILE* stream = freopen("output.txt", "w", stdout);

or its security-enhanced alternate version:

    errno_t err = freopen_s(&stream, "output.txt", "w", stdout);

The customer reported that this worked exactly as exepcted, but the output file is opened for exclusive access. They want another process to be able to read from the output file while the original process is writing to it, but the exclusive access prevents that.

The Microsoft-specific function _fsopen lets you specify a custom sharing mode, but there is no corresponding _fsreopen function that augments the freopen function with a sharing mode.

Is there anything the customer can do?

The C/C++ runtime library folks suggested using _dup2 to remap the file descriptor. Something like this:

#include <fcntl.h>
#include <io.h>
#include <stdio.h>
#include <windows.h>

// All error checking omitted for clarity
int main()
  // Open with desired sharing mode
  HANDLE h = CreateFileW(L"output.txt", GENERIC_WRITE, FILE_SHARE_READ,
                         nullptr, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL,

  // Convert to a file descriptor
  int fd = _open_osfhandle(reinterpret_cast<intptr_t>(h), _O_WRONLY);

  // Remap stdout's file descriptor to be a copy of the one we just created
  _dup2(fd, _fileno(stdout));

  // Don't need our file descriptor any more

  printf("Hello, world!\n");

  return 0;

The customer confirmed that this does exactly what they needed.

Comments (10)
  1. What’s with the _ before function names? Couldn’t Microsoft just call them “OpenOSFileHandle”, “Dup2”, “FileNo”, and “Close”?

    1. kantos says:

      No, they are extensions provided by the CRT. They are not encouraged for use by any stretch or meaning of the term. That includes the POSIX functions which MS only provides for compatibility with people too lazy to use the standard functions. These are not Operating System functions and don’t follow WIN32 conventions, because they are not windows maintained.

      1. David-T says:

        Erm, standards compatibility is not about laziness.

    2. M Hotchin says:

      In particular the C and C++ standards reserve all identifiers beginning with an underscore to the implementation.

      So, starting with ‘_’ means they will not conflict with any other properly named identifier.

    3. Harry Johnston says:

      There’s a footnote in the ISO C standard which reads “This implies that a conforming implementation reserves no identifiers other than those explicitly reserved in this International Standard”. I’m not sure that was intended to apply when the program explicitly includes a non-standard header file, though. I generally leave that sort of thing to the language lawyers.

    4. hyperman says:

      AFAIK, C has a rule in their standard: Names starting with an underscore are reserved for internal use by the OS/standard library. You are not allowed to create functions/variables/… starting with an underscore. OTOH, the standard library should only provide either the functions defined by the standard AND functions starting with an underscore. This allows you, the programmer, to define functions without having a name clash with your OS vendor.

      Both standard library providers and users have an tendency to ignore this rule. You might argue these things are the only names defined by the windows OS that are actually correct usage of C ;-)

    5. Jon says:

      Since “dup2” isn’t a “reserved” name in the C standard, a legal C program can define a global function with that name. If the C runtime defined a global function with the same name, things would go horribly wrong. So the C runtime uses “_dup2” instead. That is a “reserved” name, since it starts with an underscore, so a legal C program cannot define a global function with that name.

      (In practice all compilers will let you define functions with most names starting with an underscore, since the same compiler is used to compile the C runtime. But that’s technically a compiler-specific extension to the C standard. And choosing certain names will break things. Exactly which names and what breaks is not documented and may change between compiler releases. And if it breaks that’s your fault and not a compiler bug).

  2. The_Assimilator says:

    Reference for the lazy, or until the next time Microsoft decides to break its docs site:

    1. Kevin says:

      Since _dup2 is mostly or entirely conformant to POSIX, you can also just look up dup2(2) in any Unix manual (including the ones which various kind people have published on the internet) and it should be approximately correct. The description published by The Open Group is (intended to be) authoritative, but is a tad harder to read because of all the “shall” verbiage.

  3. Tanveer Badar says:

    What is wrong with fprintf() or similar? And since it is C++ (in the example at least, your support link is broken), why couldn’t their functions take an basic_ostream&, and be done with it?

Comments are closed.

Skip to main content