Silverlight: Bugs in the multicast client Announcing: Your Last About Dialog (YLAD)

Windows Phone 7: The kind of bug you don't want to discover

Published on Thursday, November 10, 2011 3:49:00 PM UTC in Programming

I have strong faith in Microsoft's code quality. When I run into problems and errors in my components, I always assume I did something wrong. Why shouldn't I? In almost all cases it indeed is me who has done something wrong - apparently I'm very good at screwing up :). Unfortunately, in some cases it's not me.

"Unfortunately"? Yes. When it's my fault that code is not behaving correctly, I can simply go ahead, review or debug, and fix it. If it's a bug in the runtime or platform however, I have to find a way around it somehow, and a million other people are potentially affected by it too. Seems like the worse alternative to me. This posts describes a particular bug with WP7 developing and hopefully saves some of you some time in the future.

The problem

I was working on some conversion code for a special timestamp format used in a network protocol and actually ported some really old C++ code of mine for that particular case, when I suddenly realized that the results of that conversion were off. A lot. Since the code worked perfectly ten years ago, and the port to C# also looked fine to me, I started debugging and eventually found the cause. Take a look at this particular code; it uses a hard-coded value to make it more reproducible, but the real-world application has changing values, and it happens with all of them:

// create a test value > UInt32.MaxValue, but < UInt64.MaxValue

double testDouble = UInt32.MaxValue * 3529921069.486;

Debug.WriteLine(testDouble < UInt64.MaxValue); // just to be sure; this prints "True"

// cast to UInt64; we could also use Convert.ToUInt64

UInt64 testUInt64 = (UInt64)testDouble;

// output the results

Debug.WriteLine("Double: " + testDouble);

Debug.WriteLine("UInt64: " + testUInt64);

If you use this code for example in a .NET 4 console application, the output is as expected:

True Double: 1,51608955473738E+19 UInt64: 15160895547373793280

Now use the same code, but run it in a Windows Phone 7 application, for example in a button click event handler. The output is:

True Double: 1.51608955473738E+19 UInt64: 9223372036854775808

Uhm... what? As you can see, the cast value is not anything near the original double value, or the expected result. I haven't looked at the internals or thought about how this particular result is produced, but it's interesting that this equals *((UInt64)Int64.MaxValue + 1) *and that you get that result for all kinds of input values (the hard-coded initial factor in the code above does not matter).

That's bad, but fortunately not the worst case: the bug only happens in the emulator. If you run the same code on a real device it behaves as expected (at least on the one device I've tested the code on, a Samsung Omnia 7):

True Double: 1,51608955473738E+19 UInt64: 15160895547373793280

Workaround

If you want your code to behave correctly in the emulator too, you can apply the following workaround:

// create a test value > UInt32.MaxValue, but < UInt64.MaxValue

double testDouble = UInt32.MaxValue * 3529921069.486;

Debug.WriteLine(testDouble < UInt64.MaxValue); // just to be sure; this prints "True"

// cast to UInt64 correctly (workaround)

UInt64 testUInt64;

if (testDouble > Int64.MaxValue)

{

    testUInt64 = (UInt64)(testDouble - Int64.MaxValue) + Int64.MaxValue;

}

else

{

    testUInt64 = (UInt64)testDouble;

}

// output the results

Debug.WriteLine("Double: " + testDouble);

Debug.WriteLine("UInt64: " + testUInt64);

Conclusion

I hope that the next time you're doing some conversions and pull your hair out over faulty behavior of your code, you remember this post and that there's apparently some fundamental bug with it in the WP7 emulator. If you have more information on this or thoughts you'd like to share, please comment or contact me.

Edit: the corresponding Connect entry can now be found here:

Windows Phone Emulator cast double/UInt64 bug

Tags: Bug · Emulator · Mango · Windows Phone 7