Hi all. First post on the forum.
I'm writing a generic funtion to open files along my program, but am worried if the pointers are being closed correctly.

The function definition:

FILE* openfile(char *FileName, char *Mode)
	{
	FILE *TempFile;
	if((TempFile = fopen(FileName, Modo)) == NULL)
		{
		fprintf(stderr, "Couldn't open file '%s'. Does it exist? Do you have permission to read it?\n", FileName);
		exit(1);
		}
	return(TempFile);
	}

Calling the function in main:

int main(int argc, char **argv)
{
/* blahblahblah */
FILE *thefile;
char *thefilename;

thefilename = argv[1];
thefile = openfile(thefilename, "r");

/* uses the file */

fclose(thefile);
return(0);
}

What I'd like to know is if fclose(thefile) is closing all references to the file opened. That's because in the function we have TempFile actually opening the file. Is TempFile's reference also being closed when we call fclose(thefile) in main?
Thanks a lot.

Dani AI

Generated

Brief answer and what actually happens: closing a stream is an operation on the FILE object and the underlying OS descriptor — it flushes buffers, closes the descriptor and releases the stream's resources. Pointers that once pointed at that FILE do not automatically become "closed"; they become dangling. If several pointers refer to the same stream, calling fclose once is enough; calling fclose again through another pointer is undefined behavior. This restates and expands on 's point.

How to pass and open safely (patterns): pass a FILE * by value when the callee only uses the stream. If the callee must open the stream for the caller, either return the FILE * (return NULL on failure) or accept an out-parameter (FILE **) and assign *out = ... inside the function. Library helpers should not call exit() on failure; return an error and let the caller decide. A safe, minimal approach is shown below.

int open_file(FILE **out, const char *path, const char *mode)
{
    FILE *tmp = fopen(path, mode);
    if (!tmp) return -1;          /* caller handles error, check errno if needed */
    *out = tmp;
    return 0;
}

Safe close helper and checklist: use a small utility to avoid double-close and dangling pointers.

void safe_fclose(FILE **fp)
{
    if (fp && *fp) {
        if (fclose(*fp) != 0) perror("fclose");
        *fp = NULL;
    }
}

Additional practical notes: check fopen/fclose return values and use errno/strerror or perror for diagnostics; prefer const char * for names/modes; avoid multiple owners of the same FILE (one owner = one closer); globals/static give lifetime but hurt modularity and reentrancy (as discussed by and ); never dereference an uninitialized FILE * (that commonly causes the segfault mentioned). These practices prevent leaks, double-closes and the common runtime traps in C file handling.

Recommended Answers

All 9 Replies

if fclose(thefile) is closing all references to the file opened

fclose doesn't close references. It closes a FILE object.
It doesn't matter how many pointers point a particular one. It was opened once, and it must be closed also once.

Nezachem, thanks for the input. I thought about it but wasn't 100% sure.
Do you have any suggestion on how I could pass the global FILE* by reference?
I can't use something like:

void openfile(FILE *tempfile, char *filename, char *mode)
{
/* blahblahblah */
}

And call this way:

openfile(thefile, filename, "r");

Because it gives me a segmentation fault when the program is run, though the compilation goes ok.
Thanks in advance.

FILE * is a pointer. if you want to pass it by reference, make it a pointer to a pointer, FILE **

Hi there, Jephthah.
If I define the function this way so it can take a FILE** as argument:

void openfile(FILE **TempFile, char *FileName, char *Mode)
{
if((TempFile = fopen(FileName, Mode)) == NULL)
   {
   fprintf(stderr, "Error opening the file... next please.\n");
   exit(1);
   }
}

The compiler gives me this warning:
"assignment from incompatible pointer type", and points to the fopen line.
Maybe there is a better way to write it?
Thanks in advance.

because now it's a pointer so you need to dereference it when you want to make an assignment to it. line 3 becomes:

if(( *TempFile = fopen(FileName, Mode) ) == NULL)

Thanks, Jephthah. It works, but I'm saving your solution for something bigger.
I just tried declaring the file pointer outside the main() function, so FileOpen() procedure could access the pointer since it is global now. Sometimes less is more.
It is stressing to write a text parser in C, and AWK just proved to be too slow for the needed task.
Thank you very, Daniweb is a fountain of knowledge.

globals are widely considered poor programming. you should learn to not use them, by not using them unless you have a condition where it's necessary to do so.

You think "it works" for you now, but it's a Faustian bargain. And it will come back to haunt you.


.

Hi there, Jephthah.
You are right about global variables being bad if one abuses their use without care. For this, we have the static modifier in C, which I'm using.for this task. :-)
I tend to compare this to the "don't use goto because it's not necessary". The new programmers are inflated by this, but they never touched, for example, a compiler, so they don't know that a compiler can't be written without goto, and Aho reinforces this.
That's why goto was left in C. And Dijkstra, the greatest programmer that ever existed, never intended to abolish the use of goto when he invented the structured programming 40 years ago (though he discouraged its use whenever possible).

commented: gtfo -1

yeah. okay. sure.

:icon_rolleyes:

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.