Path: utzoo!attcan!uunet!snorkelwacker!bloom-beacon!eru!luth!sunic!tut!tukki!tarvaine From: tarvaine@tukki.jyu.fi (Tapani Tarvainen) Newsgroups: comp.lang.c Subject: fopen() and memory shortage Message-ID: <2935@tukki.jyu.fi> Date: 6 Feb 90 11:53:59 GMT Reply-To: tarvaine@tukki.jyu.fi (Tapani Tarvainen) Organization: University of Jyvaskyla, Finland Lines: 56 Two days ago I had this little trouble with a program which, to make it brief, reads a file into memory, does something to it and writes it back, saving the original as a backup with another name (= an editor). Normally it works just fine, but in this instance it complained "can't open file for writing"; I then exited without saving and found that it had destroyed the original file but failed to back it up. The relevant code looks something like this: if (fexist(fname)) /* backup */ if (!(fp = fopen(fname,"w)) /* error message */ I soon found out that fexist() returned 0 even though the file definitely existed. Here's what fexist() looked like (slightly trimmed): int fexist(fname) char *fname; { FILE *fp; if ((fp = fopen(fname, "r")) == NULL) return(0); fclose(fp); return(1); } I had to sleep over it before I figured out what's wrong: fopen() needs memory for buffering, and there wasn't enough left. I replaced fopen() and fclose() with open() and close(), and presto! it worked. I can't help wondering why the author had used buffered calls in the first place, since nothing is read from the disk anyway; is there some situation where open()/close() wouldn't work (are they less portable perhaps)? After fixing fexist() I'm now in a situation where the backup will be created properly, but saving the file still doesn't succeed. The fopen() fails, but open() inside it succeeds, effectively destroying the file. I can think of a couple of ways to handle this, but I don't really like any of them: (1) using unbuffered I/O for the writing (yuck!); (2) malloc()ing the buffer earlier and writing my own buffered output routine (feels like re-inventing the wheel); (3) malloc()ing enough memory earlier and free()ing it just before the fopen() (kind of silly, and where do I figure out how much memory fopen() needs -- portability is an issue); (4) keeping a stream open throughout for all writes. Suggestions, anyone? (I am using TurboC 2.0 in MS-DOS, if it matters.) -- Tapani Tarvainen (tarvaine@jyu.fi, tarvainen@finjyu.bitnet)