The third one also needs a try/finally to guarantee (for some definition of the word) that the file gets closed.
With the code as-is, you can introduce errors elsewhere in the program by renaming the log file, creating a directory with the same name, waiting a while for the process to run out of file descriptors, and then deleting the directory and undoing the rename. Conversely, the function can throw if another part of the program keeps too many files open.
With the code as-is, you can introduce errors elsewhere in the program by renaming the log file, creating a directory with the same name, waiting a while for the process to run out of file descriptors, and then deleting the directory and undoing the rename. Conversely, the function can throw if another part of the program keeps too many files open.