Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is this Macro Abuse?

I was reverse engineering some code and came across this...

/************************************************************************/
/*                                                                      */
/*                          MACRO CHECK_FREAD                           */
/*                                                                      */
/*  CHECK_FREAD is used to check the status of a file read.  It         */
/*   is passed the return code from read and a string to print out if   */
/*   an error is detected.  If an error is found, an error message is   */
/*   printed out and the program terminates.  This was made into a      */
/*   macro because it had to be done over and over and over . . .       */
/*                                                                      */
/************************************************************************/

#define CHECK_FREAD(X, msg)  if (X==-1) \
                 { \
                return(DCD_BADREAD); \
                 }

Basically, the particular set of functions in this file call this whenever they do a (c-read) to check the result for an error. They also have a similar check for EOF... Basically as far as I can tell, they're doing it this way to insert returns on error in the middle of their function in a bunch of places.

e.g.

/*  Read in an 4                */
    ret_val = read(fd, &input_integer, sizeof(int32));

    CHECK_FREAD(ret_val, "reading an 4");
    CHECK_FEOF(ret_val, "reading an 4");

    if (input_integer != 4)
    {
        return(DCD_BADFORMAT);
    }

    /*  Read in the number of atoms         */
    ret_val = read(fd, &input_integer, sizeof(int32));
    *N = input_integer;

    CHECK_FREAD(ret_val, "reading number of atoms");
    CHECK_FEOF(ret_val, "reading number of atoms");

Now I'm just getting back into c/c++ programming, and I never used macro's much in the first place, but is this macro abuse?

I read this... When are C++ macros beneficial?

...and it doesn't sound like any of the kosher examples, so my guess would be "YES". But I wanted to get a more informed opinion rather than just making educated guesses... :)

...errr, wouldn't it be better to use some sort of wrapping?

like image 950
Jason R. Mick Avatar asked Sep 02 '10 18:09

Jason R. Mick


1 Answers

Because it's not the same. If you put the same thing into a function, you'll have a short function that returns DCD_BADWRITE if X equals -1. The macro in question however returns from the containing function. Example:

int foobar(int value) {
    CHECK_FREAD(value, "Whatever");
    return 0;
}

would expand to:

int foobar(int value) {
    if (value == -1) {
        return (DCD_BADWRITE);
    };
    return 0;
}

If, however, it were a function, the outer function (foobar) would happily ignore the result and return 0.

A macro that looks so much like a function, but behaves differently in a crucial way, is a major no-no IMO. I'd say yes, it is macro abuse.

like image 83
tdammers Avatar answered Oct 10 '22 18:10

tdammers