#freopen() clarification

77 messages · Page 1 of 1 (latest)

jaunty sorrel
#

Would this be safe:

UD.file = tmpfile();
UD.file = freopen( NULL, "w+", UD.file );

Or do I need to hold freopen's return value elsewhere briefly so that I keep hold of UD.file in case freopen fails?

serene gulchBOT
#

When your question is answered use !solved to mark the question as resolved.

Remember to ask specific questions, provide necessary details, and reduce your question to its simplest form. For tips on how to ask a good question use !howto ask.

short idol
#

The standard says "The freopen function first attempts to close any file that is associated with the specified stream.Failure to close the file is ignored." So I think it always closes the old file

jaunty sorrel
#

That's only in the case filename is specified in, the case it's not it say this:```
If filename is a null pointer, the function attempts to change the mode of the stream. Although a particular library implementation is allowed to restrict the changes permitted, and under which circumstances.

#

Doesn't say anything about closing the file in that case

short idol
#

The case for NULL filename even says "as if the name of the file currently associated with the stream had been used"

jaunty sorrel
#

which doc you reading?

short idol
#

7.23.5.4 The freopen function

#

I guess it does say that "Failure to close the file is ignored" so it may still be open at the end but idk how you'd check for that

#

I don't think the standard provides a way to check if the file is still open

jaunty sorrel
#

hmm, guess I'll need to just skip the FILE* interface and just use the raw interfaces instead with wrappers. That's annoying but workable, better than UB

short idol
#

Where would the UB come from?

jaunty sorrel
#

The UB is wether the stream parameter is still open in the case of failing to change mode

#

and since the standard doesn't clearly define that it's UB

short idol
#

Leaving a file open isn't UB

jaunty sorrel
#

but that's the thing, if freopen fails and returns NULL it's not clear if I should then attempt to close what I gave the stream parameter

#

I either risk a dangling file pointer when existing after a failed reopen or risk a segfault by trying to close it. Neither is a good solution honestly

#

Well anyways no that it's been made clear to me the particular scenario I needed clarifying is UB

#

!solved

serene gulchBOT
#

Thank you and let us know if you have any more questions!

This thread is now set to auto-hide after an hour of inactivity

devout crag
short idol
#

But it says it first closes the file

jaunty sorrel
#

which would make the stream invalid

devout crag
#

how could you say recover from freopen failing when using it with stdout

#

if you couldn't close stdout afterwards

jaunty sorrel
#

I wouldn't do that in the 1st place

devout crag
#

it's definitely one of the intended use cases

jaunty sorrel
#

I would be dabbling with the raw handles in that case since I don't want UB

devout crag
#

strange

jaunty sorrel
#

I wish there was something like fchangemode() which at least would be clear about not closing the file ever

devout crag
jaunty sorrel
#

Ah, yeah that one's just a bug on my part, forgetting to put the line after the if statement

devout crag
#

the wording about it seems pretty clear to me now

#

it says it first attempts to close the stream

jaunty sorrel
#
that specified by mode``` indicates to me it tries to keep the file open instead in that particular scenario
#

if it had been said "freopen in both cases first closes..." then yeah, it would be clear what happens but it doesn't so it's not

devout crag
#

well glibc closes the file even in this case

devout crag
jaunty sorrel
#

and what about crt? or whatever the mac version does?

jaunty sorrel
devout crag
#

doesn't even mention that filename can be null

jaunty sorrel
#

So now there's implementation UB too? Yeah I'm not going to use the standard FILE* for this particular scenario, too unreliable

devout crag
#

basically you shouldn't interpret filename being null as a special case where all of the other wording has no effect, just think of it as being a default where it fills in the current file name

#

so the rule about closing the file still applies

devout crag
#

like _wfopen

jaunty sorrel
#

Not really, I think there was some prefix that could add to paths to allow extended UTF-8 paths

devout crag
#

:)

jaunty sorrel
#

Yeah, one problem at a time please

devout crag
#

if you create an unpaired surrogated code unit then you can't open it with a UTF-8 path

jaunty sorrel
#

I can circle back to the non-unicode paths issue later after I've gotten my project to do it's expected tasks in unicode

devout crag
#

but I don't really see how your interpretation could make sense

#

If filename is a null pointer, the freopen function attempts to change the mode of the stream to
that specified by mode, as if the name of the file currently associated with the stream had been
used. It is implementation-defined which changes of mode are permitted (if any), and under what
circumstances.

The freopen function first attempts to close any file that is associated with the specified stream.
Failure to close the file is ignored. The error and end-of-file indicators for the stream are cleared.
Section 7.23.5.4 "The freopen function" Paragraphs 3 and 4 C23

jaunty sorrel
#

Neither do I see it making implementation sense, the fact remains however the standards left it open to interpretation by not defining clearly what should happen

devout crag
#

clearly, it closes the file first before attempting to change the mode

#

given that it says first

jaunty sorrel
#

No it doesn't, it doesn't make clear that it doesn't just apply to the renaming situation but to the mode change situation also

#

It's left up in the air as what was actually meant so it's implementation defined at that point which makes it UB in my book

devout crag
#

do you also think the error and end of file indicators aren't cleared when changing the mode?

#

that should be much easier to verify

jaunty sorrel
#

It's possible, though in this particular case it doesn't matter as nothing was written by this point anyways

devout crag
#

I just don't think you're reading it correctly

jaunty sorrel
#

I expect this file to live in ram only for it's lifetime so it's completely ok for it to still be at position 0 with length 0 when I start using it

#

I only need to be sure I've not caused a memory leak by relying on UB to be what I want it to be (which going by what you've said it is for now at least what I want it to be)

#

Ultimately the standard has not given me confidence I can still rely on the handle I was given at the start nor can I rely on the handle to be closed if freopen happens to fail (albeit unlikely in this particular scenario)

devout crag
#

also was there anything wrong with just using binary mode

#

(if it's fine, then you can get around thinking about this)

jaunty sorrel
#

on posix no, but on windows it is mentioned that text mode is needed to get the expected behaviour

#

I forgot where I read that but either way it means I should still switch to text mode to eliminate a potential cause of my corrupted text

stiff lake
#

freopen uses the open syscall under the hood I think

#

man 3 freopen says:

ERRORS
       ...
       The fopen() function may also fail and set errno for any of the errors specified for  the routine open(2).
       ...