Lab overview
Lab 01
Lab 02
Lab 03
Lab 04
Lab 05
Lab 06
Lab 07
Lab 08
Lab 09
Lab 10
Lab 11
Lab 12
Lab 13
Review

[Course home page]

CSC 209 lab 10 solutions, week of 19 July 2022

Question 5:

Problem:
A function which returns true/false to indicate whether the argument exists and is a plain file (much like "test -f"):

Code:

int fexists(char *file)
{
    struct stat *p;
    p = malloc(sizeof(struct stat));
    return(stat(file, p) == 0 && S_ISREG(p->st_mode));
}

Solution:

int fexists(char *file)
{
    struct stat statbuf;
    return(stat(file, &statbuf) == 0 && S_ISREG(statbuf.st_mode));
}

The second argument to stat() is a pointer, and that leads some beginning C programmers to feel that they need to declare a pointer variable. Some people do worse than the original code above in that they pass 'p' to stat() uninitialized, thus supplying an effectively random pointer value.

But stat() expects a pointer to an area where it can store all the stat data. The easiest way to create such an area is not malloc(), but a simple variable declaration.

This evades a bug in the original code, in that malloc() can return NULL if more memory isn't available; the original didn't check for that, so if malloc() returned NULL it would segfault in stat().

It fixes a subtler error in the original too: the original is a "memory leak" because each time you call it it does an additional malloc(). If this is in a long-running program (e.g. something like a web server) then it will eventually run out of memory. Malloc() is slow, and introduces a bookkeeping obligation (you have to make sure you free the memory eventually). Variable declarations are much quicker to execute, and are easier to write. Keep it simple!


[press 'back' in your web browser to return to the problems]