In the mold of a previous question I asked about the so-called safe library deprecations, I find myself similarly bemused as to why fopen()
should be deprecated.
The function takes two C strings, and returns a FILE* ptr, or NULL on failure. Where are the thread-safety problems / string overrun problems? Or is it something else?
Thanks in advance
The
fopen_s()
function has been added by Microsoft to the C runtime with the following fundamental differences fromfopen()
:Essentially it means that files the application writes are protected from other users by default.
They did not do this to
fopen()
due to the likelyhood that existing code would break.Microsoft has chosen to deprecate
fopen()
to encourage developers for Windows to make conscious decisions about whether the files their applications use will have loose permissions or not.Jonathan Leffler's answer provides the proposed standardization language for
fopen_s()
. I added this answer hoping to make clear the rationale.You can use
fopen()
. Seriously, don't take any notice of Microsoft here, they're doing programmers a real disservice by deviating from the ISO standards . They seem to think that people writing code are somehow brain-dead and don't know how to check parameters before calling library functions.If someone isn't willing to learn the intricacies of C programming, they really have no business doing it. They should move on to a safer language.
This appears to be just another attempt at vendor lock-in by Microsoft of developers (although they're not the only ones who try it, so I'm not specifically berating them). I usually add:
(or the
"-D"
variant on the command line) to most of my projects to ensure I'm not bothered by the compiler when writing perfectly valid, legal C code.Microsoft has provided extra functionality in the
fopen_s()
function (file encodings, for one) as well as changing how things are returned. This may make it better for Windows programmers but makes the code inherently unportable.If you're only ever going to code for Windows, by all means use it. I myself prefer the ability to compile and run my code anywhere (with as little change as possible).
As of C11, these safe functions are now a part of the standard, though optional. Look into Annex K for full details.
Some implementations of the FILE structure used by 'fopen' has the file descriptor defined as 'unsigned short'. This leaves you with a maximum of 255 simultaneously open files, minus stdin, stdout, and stderr.
While the value of being able to have 255 open files is debatable, of course, this implementation detail materializes on the Solaris 8 platform when you have more than 252 socket connections! What first appeared as a seemingly random failure to establish an SSL connection using libcurl in my application turned out to be caused by this, but it took deploying debug versions of libcurl and openssl and stepping the customer through debugger script to finally figure it out.
While it's not entirely the fault of 'fopen', one can see the virtues of throwing off the shackles of old interfaces; the choice to deprecate might be based on the pain of maintaining binary compatibility with an antiquated implementation.
Thread safety.
fopen()
uses a global variable,errno
, while thefopen_s()
replacement returns anerrno_t
and takes aFILE**
argument to store the file pointer to.There is an official ISO/IEC JTC1/SC22/WG14 (C Language) technical report TR24731-1 (bounds checking interfaces) and its rationale available at:
There is also work towards TR24731-2 (dynamic allocation functions).
The stated rationale for
fopen_s()
is:The specification says:
6.5.2.1 The fopen_s function
Synopsis
Runtime-constraints
None of
streamptr
,filename
, ormode
shall be a null pointer.If there is a runtime-constraint violation,
fopen_s
does not attempt to open a file. Furthermore, ifstreamptr
is not a null pointer,fopen_s
sets*streamptr
to the null pointer.Description
The new versions do parameter validation whereas the old ones didn't.
See this SO thread for more information.