2

errno_t freopen_s ( FILE** pFile, const char *path, const char *mode, FILE *stream );

Here, the freopen_s disassociates the FILE pointer stream from whatever it is pointing at, then associates it with the file that is located at path. The mode defines the limits for what could be done with this specific pointer stream.

As far as I can tell, all these are nothing different than what would happen with:

...
fclose( stream );
fopen_s( &stream, path, mode );
...

My question is: What does the pFile do there? freopen also has it, as the return value. From all the examples I have seen, pFile, after the call, also points at the same file that is located at path. So:

...
fclose( stream );
fopen_s( &stream, path, mode );
fopen_s( pFile, path, mode );
...

Is this really it?

Utkan Gezer
  • 3,009
  • 2
  • 16
  • 29
  • freopen() does it atomically, rather important when you have threads that also write to the same stream. – Hans Passant Feb 08 '14 at 18:03
  • I understand that, and would rather prefer that in any day. However, I don't understand why it is assigning one *filepath* to 2 *FILE pointers*... I can see no benefit of it. And in whichever example I have seen, the assignment to `FILE* pFile`, or the return value is left unused. – Utkan Gezer Feb 08 '14 at 20:54
  • I assume you are talking about the secure version, freopen_s(). It makes sure that your FILE* is NULL when you do it wrong. Far too many C programmers ignore the return value, like you want to do, blindly hoping that it worked and then continue to write to a non-existing file. Which turns your program into a zombie that's a willing participant in a handle recycle attack. – Hans Passant Feb 08 '14 at 22:51
  • @HansPassant I have been talking for both `freopen_s` and `freopen`. In both, the `FILE *` (pseudo-returned by `freopen_s` and actually returned by `freopen`) is not used with regards to what it can achieve; be the reference to a file. Your assumption is wrong, I have no such desire to ignore the return value. In fact, I need it. But I need a simple return value, indicating failure/success, not a big fat FILE pointer. And as you can see, even MSDN doesn't use the first argument passed inside the secure version, instead it uses the errno_t true return value: http://goo.gl/5SYM0C – Utkan Gezer Feb 09 '14 at 01:05
  • I have no clue what the hangup might be, the example you linked even uses the returned *stream*. A FILE* is not fat. If you want to use freopen() then you check for a NULL return value to detect failure and use *errno* to find out why. Standard C way. – Hans Passant Feb 09 '14 at 01:50
  • @HansPassant It uses the returned *stream*, but then it doesn't use the *stderr*... If it was using the *stderr*, then it wouldn't use the *stream*. Same thing; because *stderr* and the *stream* **are** the same thing. Well, it can also use one and then the other in an alternating manner... Whatever, what I'm trying to say is, it apparently returns the same pointer twice, and I have no idea why would it do that... Either one of them can be completely ignored, and I cannot see what use this could bring about. – Utkan Gezer Feb 09 '14 at 12:50
  • I guess the hangup is that you keep reasoning what happens if the function doesn't fail. The returned FILE* is **not** the same when the function fails, it will be NULL. – Hans Passant Feb 09 '14 at 13:13
  • @HansPassant Well in the case of error, the *errno_t* return value from `freopen_s` already indicates the error, still no apparent need for the FILE pointer *stream*. As for the `freopen`, this time there is no need for the return value with the type FILE pointer, instead it could be an errno_t, since its sole use should have been error indication... Currently it can be a useless identical variable in case of success. – Utkan Gezer Feb 09 '14 at 13:54

1 Answers1

1

When you continue reading the help that is referenced in your question you find the answer:

`freopen_s` is typically used to redirect the pre-opened files stdin, stdout, 
and stderr to files specified by the user.

So it is not intended that you use a self defined FILE pointer to freopen. Instead it affects the probably widely spreaded used stdout etc.

Regarding your question "Is this really it?": yes.

Edit: Regarding the other question: My question is: What does the pFile do there?

The pFile parameter to the function freopen_s is a pointer to a FILE*. The function can allocate a new FILE object an return the new pointer with pFile. There might be run-time libraries that doesn't allocate a new object but change the FILE structure that is passed indirectly by *pFile. But this is strongly implementation dependent.

Further the non-atomic operation may fail after the fclose part. In that case the run-time may change the pointer that is passed with pFile to NULL.

harper
  • 13,345
  • 8
  • 56
  • 105
  • But why is there a `FILE **pFile` argument to be issued for `freopen_s`, and why is there a `FILE *` return value for `freopen` at all then? `freopen_s( anything, path, mode, stdout );` redirects the `stdout` to `path`, without that `anything` being anything really important at all... And as for `freopen` counterpart, the return value serves no purpose other than indicating the error when an error occurs; but why a massive `FILE *` structure type return for something like that, instead of an `errno_t` (int), or even any `char`? – Utkan Gezer Feb 08 '14 at 17:30
  • The return value of functions like `freopen_s` and `strcpy` might be a good topic for the next question, but probably you can search for it. If you think you got an answer, you could click on the "accepted" check mark. – harper Feb 10 '14 at 11:38
  • Sorry, I would if I had, but the only answer I have received for my real question (indicated with "My question is: ...") is that "`pFile` is for indicating failure", which was not thanks to this only answer. And, honestly, I already knew that anyway... I was rather expecting my question to be interpreted as "Why are there two values that are dedicated for error indication, one of which requiring you to pass a pointer to a FILE pointer?". But hell, since apparently there isn't any legitimate answer to that, I would accept an "it's for indicating failure", but this answer doesn't do that – Utkan Gezer Feb 10 '14 at 16:14
  • 1
    @ThoAppelsin Have you got a good answer to your question? I 100% agree with what you're saying, and I'm tired of very smart and experienced people on here trying to defend terrible design decisions made by Microsoft. I constantly get downvoted for asking such questions about why Windows does things in particular ways I consider terrible. You're right, you end up with a useless pointer, it's also useless as an indicator of an error as you already have an error value returned to you. Please tell me I'm wrong and that pointer's there for a reason. – Zebrafish May 25 '16 at 14:05
  • 1
    @ThoAppelsin I found this on a forum posted in 2005: "You're right, we could have made the first parameter of freopen_s accept NULL, since the return value of the original freopen is not often used. Instead, the return value of fopen cannot really be ignored. I opened a bug about freopen_s and we will try to improve it in the next releases." – Zebrafish May 25 '16 at 14:10
  • @TitoneMaurice It took me a while to figure out what happened here 2 years ago. The question doesn't look too familiar to me, let alone any answer I may have found to it back then. I am sorry. – Utkan Gezer May 26 '16 at 01:09