Note that there are some explanatory texts on larger screens.

plurals
  1. POIf statement evaluates to false but still branches as if it was true
    primarykey
    data
    text
    <p>I am quite stumped. In an async method, I have a few initial guard statements, that throw exceptions if specific conditions are met. </p> <p>One of them is the following:</p> <pre><code>var txPagesCount = _transactionPages.Count; if (txPagesCount == 0) throw new InvalidOperationException(string.Format("Cannot commit transaction {0}. It is empty.", _txId)); </code></pre> <p>This is supposed to ensure there are pages in the <code>_transactionPages</code> dictionary and throw if there are none.</p> <p>This is what happens when I run it (release and debug build, debugger attached):</p> <p><img src="https://i.stack.imgur.com/BAMrV.png" alt="Number of pages is 3"></p> <p>So the number of pages in the dictionary is 3.</p> <p><img src="https://i.stack.imgur.com/ufZ1R.png" alt="if statement evaluates to false"></p> <p>And so, as expected, the if statement comparing 3 to 0 evaluates to false.</p> <p>But then, when stepping further:</p> <p><img src="https://i.stack.imgur.com/aypLv.png" alt="Steps into the branch"></p> <p>It steps into the branch as if the if statement evaluated to true, and throws the exception.</p> <p>What am I missing here?</p> <p><strong>UPDATE</strong></p> <p>When I do this:</p> <pre><code>private static readonly object _globalLock = new object(); public async Task&lt;Checkpoint&gt; CommitAsync(PageNumber dataRoot, PageNumber firstUnusedPage) { lock (_globalLock) { if (IsCompleted) throw new InvalidOperationException(string.Format("Cannot commit completed transaction {0}", _txId)); var txPagesCount = _transactionPages.Count; if (txPagesCount == 0) throw new InvalidOperationException(string.Format("Cannot commit transaction {0}. It is empty.", _txId)); } </code></pre> <p>the if statement does not branch to throw the exception. This is the case for both debug and release build. Is something messing up the call stack? Also, if instead of the lock I add <code>System.Threading.Thread.MemoryBarrier();</code> after the <code>if</code> statement, it will not go into the branch.</p> <p><strong>UPDATE 2</strong></p> <p>The mystery becomes a bit larger. It is almost as if c++ scoping rules are used :D The code below (<strong>in debug build</strong>) will show the expected behavior: not go into the branch and not throw. In <strong>release build</strong>, it will go into the branch and throw just as before.</p> <pre><code>private static readonly object _globalLock = new object(); public async Task&lt;Checkpoint&gt; CommitAsync(PageNumber dataRoot, PageNumber firstUnusedPage) { //lock (_globalLock) { if (IsCompleted) throw new InvalidOperationException(string.Format("Cannot commit completed transaction {0}", _txId)); var txPagesCount = _transactionPages.Count; if (txPagesCount == 0) throw new InvalidOperationException(string.Format("Cannot commit transaction {0}. It is empty.", _txId)); } </code></pre> <p>If I comment out the "scoping braces" it will go into the branch and throw the exception (as in my original images).</p> <p><strong>FINAL? UPDATE</strong></p> <p>Well that sucks. I made a few changes to unrelated areas of code and now I am no longer able to reproduce the problem.</p>
    singulars
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload