For context, I am trying to do a save system for a game.

  • Gyroplast
    link
    fedilink
    153 months ago

    Generally speaking, there is a race condition lurking where the OS may do whatever to your file you just checked, rendering the check strictly obsolete the moment you get the result. This isn’t typical, but possible, and a lovely old-school security vulnerability class. :)

    A more practical argument is that you’re going to handle any errors your open() may throw, anyway, and therefore it’s simply redundant to check for file existence explicitly beforehand.

    Under specific circumstances, you may want to do explicit, very specific tests for more detailed error reporting than “error opening file!”, for example “save file is corrupted” if it’s too short or zero-length, or “save file directory is gone. What the hell, dude? Recreating it, but stop fiddling with my files!”

    This is easy to overengineer. Best is to get into the very sensible habit of always checking for errors or exceptions returned by your calls, and this will become a non-issue.

    In this particular use-case of save file loading, you might implement displaying a listing of save files in a directory with opendir/readdir or FindFirstFile/FindNextFile and its ilk, to offer a list of files to load, which doubles as a crude existence test already. Many ways lead away from Rome. If you’re considering loading an autosave and offer a “Continue” button or something, a cheap existence test would work very well to decide if that button needs to be displayed in the first place, but doesn’t free you from handling any open() errors later. You could also open() and validate an autosave directly, and when/if the user decides to “Continue”, use the already reserved file descriptor and maybe even the preloaded save data to quickly jump into the game.

    If you want a simple answer: Do not introduce race conditions. Always acquire a lock for a shared resource before doing anything with it.