====== A quick one ======
Just a quick something to keep this site alive.
These two issues were nothing that got //me// fuming angry, but my boss was not amused when I was blindsided by these two issues in a production environment.
===== One: bash ''tee'' and return values =====
There is this nice UNIX tool named `tee` that writes its standard input to a file without actually consuming it. It is very useful in scripts where you want to print the proceedings to screen while at the same time logging them somewhere:
someCommand | tee -a logfile.txt # '-a' to append instead of overwriting
It gets ugly, though, when you add this kind of logging to a script retroactively, //and fail to realize that the next step in the original script was to check if ''someCommand'' was successful//:
someCommand | tee -a logfile.txt
if [ $? != 0 ]; then …
Congratulations: Because ''$?'' returns the exit code of the //last// command executed, you just checked whether ''tee'' succeeded (e.g., in logging ''someCommand''’s failure).
Luckily, bash offers a way out: The array ''PIPESTATUS'' carries the individual exit codes of all commands in the pipe chain.
someCommand | tee -a logfile.txt
if [ {$PIPESTATUS[0]} != 0 ]; then …
===== Two: ''va_arg'' and C++ references don’t mix. =====
Consider:
#include
#include
using namespace std;
void foo( std::string & parmN, ... )
{
va_list ap;
va_start( ap, parmN );
int i = va_arg( ap, int );
va_end( ap );
}
int main()
{
std::string broken;
foo( broken, 42 );
return 0;
}
//The variable ''i'' will most likely not be set to 42.//
The reason is that most implementations of ''va_arg'' will take the address of ''parmN'' using the address operator ''&''. For a C++ reference, like in this case, this will yield the address //of the referenced variable//. You will not get the address of ''parmN'', but the address of ''broken'', and whatever you pull out of ''va_arg'' will not be what you expected.
----
These two [[http://en.wikipedia.org/wiki/Lobo_%28DC_Comics%29 | bastiches]] caused me some hurt. Be warned.