2000.04.28 02:38 "VC++ Release build causes problems", by Peter Montgomery

2000.04.28 17:27 "VC++ Release build causes problems", by Peter Montgomery

Okay, I did a binary search and destroy mission on the LZW code, using the VC++ pragma pair...

#pragma optimize( "", off )
#pragma optimize( "", on )

...which allows you to turn optimization on and off at the function level. After a couple of minutes, I had narrowed the problem down to a single function - "LZWSetupDecode( )". Since I am using VC++ 5.0 (which some have mentioned as having optimization bugs), and no one else seems able to reproduce this bug, I guess the likely culprit is a compiler problem. Since it's such a tiny module, the potential problem area seemed pretty likely. This a piece of code from the problematic fuction...

   * Pre-load the table.
  for (code = 255; code >= 0; code--) {
   sp->dec_codetab[code].value = code;
   sp->dec_codetab[code].firstchar = code;
   sp->dec_codetab[code].length = 1;
   sp->dec_codetab[code].next = NULL;

Instead of the more conventional...

  for (code = 0; code < 256; code++)

...the function steps backwards using ">=" as a the comparison. I decided to try and replace the code with the standard style loop. The result? Now instead of pixel channels with a value of 0 becoming 255, pixels with a value of 255 become 0! Arrrrgh! Okay, okay, I just need to take adeep breath. What else could Mr. Compiler be doing wrong?

A little more thinking turned up the culprit. The variable "code" is used as both a loop counter, an index into memory, and the value being assigned. I had a feeling that VC++ was converting "code" into an unsigned char and using that insetad of the int that was requested. However, the comparison was suffering from an off by one error since the compairson was to 256, a value you can't fit into an unsigned char. I added a separate unsigned char varible which I used for setting the values and directly incremented it in the loop. Problem solved. Suddenly the code worked perfectly even when optimized. Just for laughs, I returned the code to its previous form and this is what I currently have...

added to variable list...

 unsigned char VCCCompilerFix;

  VCCCompilerFix = 255;
  for (code = 255; code >= 0; code--) {
   sp->dec_codetab[code].value = VCCCompilerFix;
   sp->dec_codetab[code].firstchar = VCCCompilerFix;
   sp->dec_codetab[code].length = 1;
   sp->dec_codetab[code].next = NULL;

Oddly enough, as one point I accidentally was starting "VCCCompilerFix" at zero and incrementing while the "code" loop was starting at 255 and decrementing and the library still decoded the images perfectly. The nice thing is that I now have a fix that works. The drag is that the stupid compiler put me through this is the first place.

Thanks to everyone who pitched in!