Create an account

Very important

  • To access the important data of the forums, you must be active in each forum and especially in the leaks and database leaks section, send data and after sending the data and activity, data and important content will be opened and visible for you.
  • You will only see chat messages from people who are at or below your level.
  • More than 500,000 database leaks and millions of account leaks are waiting for you, so access and view with more activity.
  • Many important data are inactive and inaccessible for you, so open them with activity. (This will be done automatically)


Thread Rating:
  • 698 Vote(s) - 3.5 Average
  • 1
  • 2
  • 3
  • 4
  • 5
If statement appears to be evaluating even when condition evaluates to false

#1
Late At Work last night, we were trying to figure out why something was failing. A validation check was failing when it shouldn't have been.

We ended up adding a print statement to this code (disassembled from Reflector in order to check that the code was actually what we had written):

public static string Redacted(string name, DateTime lastModified)
{
long ticks = lastModified.Ticks;
if ((ticks != (ticks - (ticks % 10000L))) &&
(lastModified != DateTime.MaxValue))
{
Log.Debug(string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'",
lastModified.ToString("dd/MM/yyyy hh:mm:ss.fff"),
ticks, ticks - (ticks % 10000L)));


It printed (reformatted):

Last Modified Date = '22/03/2011 12:16:22.000'.
Ticks = '634363497820000000'.
TicksCalc = '634363497820000000'

But the condition is that "`ticks`" (which is equal to Ticks printed above) is not equal to "`(ticks - (ticks % 10000))`" (which is equal to TicksCalc)! 634363497820000000 != 634363497820000000?!

In order to determine what is going on here, we added another two statements:

long ticks = lastModified.Ticks;
/* Added following two lines: */
long num2 = ticks - (ticks % 10000L);
Log.Debug((ticks == num2).ToString());
/* */
if ((ticks != (ticks - (ticks % 10000L))) &&
(lastModified != DateTime.MaxValue))
{
Log.Debug(string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'",
lastModified.ToString("dd/MM/yyyy hh:mm:ss.fff"),
ticks, ticks - (ticks % 10000L)));

As it should have, this one printed `true` (when testing with the same value), and didn't write the second line.

Feeling a bit lost, we then removed the two lines again, recompiled, and reran. The original behaviour repeated itself.

This morning, [I recorded a video]().

The video first of all shows hitting a breakpoint in the method using the 'broken' code, then rebuilding and rerunning using the 'working' code. Note that even though the debugger displays that the `if` condition evaluates as to `false`, the body is still entered.

I've seen things like this happen before when observed by the debugger, due to the debugger forcing some things to be evaluated, but this happens whether or not the debugger is employed.

Furthermore, this only happens in Release mode (i.e. with JIT optimizations enabled).

Here are the disassembled methods for both versions: [working](

[To see links please register here]

), [not working](

[To see links please register here]

). I can't really read assembly, so am posting them here in the hopes of elucidation.

I hope that the answer isn't something obvious that I've overlooked completely...!

Edit: Here is the IL. I don't think there's anything wrong with it because it decompiles to the correct C#:

* [Not working](

[To see links please register here]

)
* [Working](

[To see links please register here]

)

**Update**:

[Confirmed as a bug by Microsoft, to be fixed in the next release](

[To see links please register here]

).
Reply

#2
Check out this thread.

[To see links please register here]


It comes down to this, you can't trust the debugger all the time.

To "fix" that if statement, add an empty **else {}** statement to it. The debugger will work as expected.
Reply

#3
That's crazy. Have you tried, for no good reason, to reorder the if statement?

if (lastModified != DateTime.MaxValue && ticks != (ticks - (ticks % 10000L))

Also, if this doesn't work (as it shouldn't, considering it shouldn't be a problem in the first place), can you show the actual IL for the code in in the problematic form?

One other thing, couldn't the `ticks` check be simplified to:

(ticks % 10000L) != 0
Reply

#4
That does indeed look like an - ahem - jitterbug. Can you set a break-point on the "if" statement and show us a screenshot of the disassembly view after it hits?
Reply

#5
I had something similar a while ago.
In my case it had to do with the fact that i was comparing 2 integer values where one value was actually a reference to a boxed integer and the other was a real primitive value.

The thing is that if you print out the value of the boxed integer and the primitive, they look the same, but comparing them is another thing. You'll get a reference comparison in stead of a value comparison.

The answer is easy:


long ticks = lastModified.Ticks;
long num2 = ticks - (ticks % 10000L);
if ((ticks != num2) && (lastModified != DateTime.MaxValue))
{ do your thing here! }


Reply

#6
I experimented a bit with simplified code:

[To see links please register here]


The most interesting variation is:

static readonly long variableZero=0;
const long constZero=0;

public static void Broken2( long ticks2)
{
long ticks = ticks2+variableZero;
if (ticks != (ticks - (ticks % 10000L)))
{
string.Format("Last Modified Date = '{0}'. Ticks = '{1}'. TicksCalc = '{2}'",
"n/A",
ticks, ticks - (ticks % 10000L)).Dump();
}
}

If I replace `variableZero` with `constantZero` it works.

----

So I'm pretty sure it is either a jitter or a compiler bug.

I've filed a bugreport on MS Connect:

[To see links please register here]


---

**Update**: The strange behavior only occurs if no debugger is attached. i.e. when Jit optimization is enabled. So I'm pretty sure it's a jitter bug.

And for people without linq-pad there is now a plain C# console project:

[To see links please register here]

Reply



Forum Jump:


Users browsing this thread:
1 Guest(s)

©0Day  2016 - 2023 | All Rights Reserved.  Made with    for the community. Connected through