home current projects technical training more about us contact us
top image

Windows vs. The C Run-Time Library for File I/O

This information augments the discussion in Chapters 1 and 2 regarding the choice between Windows and the Standard C Library (CLIB) and the more comprehensive C Run-Time Library (CRTL) when performing file I/O. The CLIB contains those functions defined by the standard and described in P. J. Plauger's book, "The Standard C Library". The CRTL includes the CLIB but also includes non-standard extensions, such as the generic string functions, extended FILE functions, _beginthreadex(), security enhancements (see the next section), and more.

Opening Comment: CRT Security Enahancements

It is a good idea to start using the security enhanced CRT where appropriate to avoid buffer overruns and other risky situations. I've upgraded many, but not all, of the example programs. A very good book, which I neglected to put in the bibliography, is "Writing Secure Code" by Michael Howard and David LeBlanc (Microsoft Press, 2003). Start with Chapter 1 and 5 (just my recommendation).

More Comments

The CLIB library advantages cited in the book are: portability, line- and character-oriented functions, and ease of use. Disadvantages include the inability to traverse directories, manage files or deal with file attributes, and the inability to use security, memory mapping, file locking, or asynchronous I/O.

Here is some supplementary information, written in terms of the advantages of using Windows rather than the CLIB. This discussion was prompted by some postings on comp.os.ms-windows.programmer.Windows and some email in response to those postings.

This discussion is confined to the Standard C library as documented, for instance, in Plauger's book. You will find that Visual C++ CRTL provides an set of extensions that allow you, for example, to lock a file. Using these extensions provides no real advantages over the Windows calls, other than allowing you to use a FILE pointer rather than a HANDLE. There is, in fact, a _get_osfhandle() function that obtains the HANDLE associated with a FILE.

  1. Direct Access to "Large Files". A "large file" is a file longer than 4GB (the limit for a 32-bit file pointer). A "small file" is shorter than 4GB. Many applications require large files, but, on the other hand, many programmers are not concerned with this issue and can use fseek(). Windows can perform direct access, using SetFilePointerEx or the offset fields in the OVERLAPPED structure, to position anywhere in a file. One email correspondent pointed out that the library functions fgetpos and fsetpos use a 64-bit file position and therefore overcome the limitation.
  2. Memory-Mapped Files. MMF provide the convenience of in-memory algorithms without I/O concerns. Chapter 5 has several examples, such as in-memory sorting and using the CLIB character and string processing functions on a mapped file. This argument is most appropriate for files that are small enough to be mapped. 3GB is the strict upper bound for 32-systems, but these limits are not an issue for 64-bit systems. The memory-mapped file performance advantages noted in Appendix C require file mapping, but, as discussed below, only apply to relatively short files when using 32-bit systems. The Examples show several instances of MM against normal file access; for instance, see cci vs. cciMM and wc vs. wcMM.

  3. File Locking. File locking is not a part of the Standard C library. The VC++ CRTL does provide a _locking() function.

  4. File and Directory Management. The SCL does not allow control (either getting or setting) file attributes (length, time stamp, etc.) nor can you scan a directory.

  5. Handle Inheritance and Redirection. A HANDLE can be inheritable and copied to a new child process, whereas a FILE pointer cannot. Likewise, standard I/O can be redirected to a handle. This is illustrated in Chapter 9 with anonymous pipes.

  6. Device Independence. A program written to use a HANDLE for I/O can be device independent; the HANDLE can be associated with a file or a pipe, for instance.

  7. Asynchronous I/O. Asynchronous I/O requires a Windows HANDLE.

Nonetheless, if you are performing simple processing of a moderate-sized file, the CLIB is hard to beat for simplicity, convenience, and even performance.

The extended C library (CLIB) provided with Visual C++ is quite rich with any number of functions that are not a part of the standard. Some, such as _popen(), allow you to perform many tasks that the book performs with Windows functions. However, while these functions are stylistically similar to the C library, they do not appear to be any easier to use and are neither Windows nor standard C. Furthermore, some functions, such as _umask(), appear to be useful, but, after examining the library source code, are found to be very limited.