Please take a look

bearophile bearophileHUGS at lycos.com
Sat Dec 22 06:14:56 PST 2007


Lukas Pinkowski:
>Taking a look at it, I see, you've done the following:
> 
> uint opCast() {
>     //return (up << 16) | low; // worse?
>     return *(cast(uint*)(cast(void*)this));
> }
>
> You really should uncomment the first line and remove the second, since
> uint* is a pointer to a 4-byte type, while your struct holds 3 bytes.
> Thus dereferencing the uint* will lead to a 4th byte with an arbitrary
> value and finally to errors.

I belive you; code similar to that ( (up << 16) | low ) was the first thing I have written.

The funny thing is that (before posting the code on this newsgroup) I have written almost 200 lines of testing code along the code for those 24 bit unsigned integers, and they have failed catching the bug you talk about :-]

This other piece of testing code too fails spotting the problem:

import std.random, u24;
int randInt(int max) {
  int k, n;
  n = max + 1;
  k = cast(int)(n * (rand / (uint.max + 1.0)));
  return (k == n) ? k - 1 : k;
}
void main() {
  Uint24[200_000] arr;
  assert(arr.sizeof == 200_000*3);

  rand_seed(10, 0);
  foreach(ref u; arr)
    u = randInt(Uint24.max);

  rand_seed(10, 0);
  foreach(i, u; arr)
    assert(u == randInt(Uint24.max));
}

Eventually I'll probably put back code like that ( (up << 16) | low ) because I must write safe code (despite being slower) but so far I have failed finding testcases that make that double casting fail :-) Can you show me an example where if shows the bug?

Bye and thank you,
bearophile


More information about the Digitalmars-d-learn mailing list