Wednesday Aug 29, 2007
I recently participated in a code inspection for my colleague, Prakash. He was fixing a bug caused by a jump into a block of code that resulted in an automatic variable failing to be initialized. Let me show you:
goto fragmented;
[deleted]
if (u1) {
[deleted]
boolean_t pruned=B_FALSE;
fragmented:
[deleted]
if (pruned && offset != 0) {
So, in the above code the variable "pruned" is not being initialized. It seemed to me that
it would either be illegal to jump in like this at all, or that it would "just work" and that
the initialization would be done. Prakash thought so too but was able to fix the problem
pragmatically by adding the line "pruned = B_FALSE;" just after the label.
I was curious, so I went to the ISO C standard and looked it up. The language used is a
bit vague, but apparently storage for automatic variables must be allocated upon entry to a
block by any means (meaning that the goto is legal) but that initialization of that storage
only occurs when the execution passed over the lines of code that declare the variable. This guarantees that the variables are initialized in a deterministic order, but in this case it means that pruned isn't initialized at all, since execution jumps to just after it is
declared.
I know you probably already knew this, but it was news to Prakash and me. Well, live and learn.
Monday Dec 11, 2006
I was trying to track down a Thunderbird bug where Thunderbird was chewing up CPU cycles. I reported this as bug 363163 at bugzilla. Anyway, I wanted to measure the CPU percentage usage as I tried out doing different things in Thunderbird.
I recently discovered Zenity, a program for displaying various graphical dialogs, including a progress meter which seemed perfect for my needs.
I used the prstat command, piped the output to grep to get rid of the unwanted lines, piped those results to cut to get the field I wanted and then piped that to zenity.
Except I didn't get anything. I was a little unsure of my syntax on the cut command, so I thought I got it wrong. I tried shortening the pipe by going further and further up the pipe.
I finally got to just the prstat and the grep. If I let it go to the screen, it appeared to work, but if I redirected to an output file, the file was always empty. What gives?
I was checking man pages, looking at the source code for grep and coming up empty. Eventually I happened to let the test run while I was looking somthing up, and lo and behold, the screen suddenly filled with all the expected output! The light dawned.
It was instantly clear to me what was going on. The stdio library buffers output. It was storing the output and then dumping it all at once when the buffer filled up. I had tried using truss to see the behavior from grep, and I could see the reads and no writes, so I assumed that it wasn't writing at all, but it was really delaying the writes. Doh!
There doesn't appear to be any way to control this behavior externally, so I just replaced the pipeline with a perl script, which does allow you to control the buffering behavior. Sometimes it is little things that bite you in the most annoying ways.
Technorati tags: programming