I know we've had a lot of nonsense about this lately, but this was really an eye-opening discovery for me and I thought I'd pass it on. Basically, I discovered this while debugging why the 32-bit version of Djinn was crashing.
A bit of background first, I have a number of functions that take a variable number of arguments, similar to how the "printf()" class of functions work. I like this because I can simultaneously print to a pipe, screen and/or log file if I so choose. What I didn't realize was that neither gcc or clang check that the format string matches the arguments unless the function prototype is declared with the "__attribute__" specifier. This is what my prototypes originally looked like:
Code: Select all
void print( const char *format, ...);
void printL( const char *format, ...);
void printX( const char *format, ...);
void printT( const char *format, ...);
void printE( const char *format, ...);
void ics_tell(const char *format, ...);Code: Select all
void print( const char *format, ...) __attribute__((format (printf, 1, 2)));
void printL( const char *format, ...) __attribute__((format (printf, 1, 2)));
void printX( const char *format, ...) __attribute__((format (printf, 1, 2)));
void printT( const char *format, ...) __attribute__((format (printf, 1, 2)));
void printE( const char *format, ...) __attribute__((format (printf, 1, 2)));
void ics_tell(const char *format, ...) __attribute__((format (printf, 1, 2)));And yes, before you start throwing stones I know that C++'s "cout << blah blah" syntax would have prevented all this, but frankly I viserally hate that syntax, so to each their own.
Anyway, I'm cleaning this up and making sure it all works cleanly. But, first I thought I'd pass this along since it may be useful to others (hence the post).
regards,
--tom