tags:

views:

408

answers:

4
+2  Q: 

A bug in .NET?

It's with great hesitation that I pose this question because I know that whenever you think you've found a bug in something like the .NET framework it's probably just you doing something wrong. Never the less, I really can't figure out what has caused my current situation.

I'm building a ray tracer in C# and in a special case the return statement of a method is never called. The strange thing is that totally unrelated things affect when this behavior takes place.

You can see the offending method here:

public Primitive FindNearest(ref float distance, Ray ray, ref RayCollision collisionResult)
{
    if (!_initialized) InitUnit();

    Primitive hitPrimitive = null;

    //Search the planes
    foreach (var plane in RenderEngine.Scene.Planes)
    {
        RayCollision collision = plane.Intersect(ray, ref distance);
        if (collision != RayCollision.Miss)
        {
            hitPrimitive = plane;
            collisionResult = collision;
        }
    }

    if (_spatialStructure == null)
    {
        //Default collision detection
        foreach (Primitive primitive in _primitives)
        {
            //RayCollision collision = primitive.Intersect(ray, ref distance);
            //if (collision != RayCollision.Miss)
            //{
            //    hitPrimitive = primitive;
            //    collisionResult = collision;
            //}
        }
    }
    else
    {
        //hitPrimitive = _spatialStructure.GetClosestIntersectionPrimitive(ray, ref distance, out collisionResult);
        //Console.WriteLine("Was here");

        RayCollision collision;
        Primitive prim = _spatialStructure.GetClosestIntersectionPrimitive(ray, ref distance, out collision);

        if (collision != RayCollision.Miss)
        {
           hitPrimitive = prim;
           collisionResult = collision;
        }
    }

    return hitPrimitive;
}

Only one thread is calling this method and on each call, the Console.Writeline statement is executed, but the return statement is never reached. The method is called hundreds of times and on each call, "was here" gets printed to the console.

If I comment out the second foreach (the one with all the comments in) the return statement is reached as normal, but the commented out code is never reached anyway. Other types of restructuring of the code can also make it run as intended but again not for any reason that makes sense to me.

This behavior looks more like some memory corruption issue one might encounter in C, so I haven't got any clues regarding what might have caused this - except a bug in .NET, that is.

Btw, the version of .NET I use is 3.5 sp1.

Update 3

In the end, it turned out that the break point had been eaten because I was in Release mode. I guess you learn something new every day.

Update 2

It seems I was so focused on the strange behavior that I didn't see the bug in my code. I have changed the code to reflect this but I'm still having the issue with never triggering the break point at the return statement - which points towards a bug in visual studio (2008) rather than .net. But my code now works, and I guess I'll have to settle with that.

Update

Here is the disassembly for stepping into the Console.Writeline function which is the last known location before the control flow disappears (There is no source code available to step into). I can't read assembly so I don't know what it means but it might make sense to someone out there.

0000002a  mov         r11,qword ptr [rbx+20h] 
0000002e  mov         rax,qword ptr [r11] 
00000031  mov         rdx,rdi 
00000034  mov         rcx,r11 
00000037  call        qword ptr [rax+000001A0h] 
0000003d  lea         rdx,[rbp+8] 
00000041  mov         rcx,rbx 
00000044  call        FFFFFFFFFFF0C410 
00000049  jmp         0000000000000050 
0000004b  jmp         0000000000000050 
0000004d  nop         dword ptr [rax] 
00000050  lea         rsp,[rbp+10h] 
00000054  pop         rdi  
00000055  pop         rbp  
00000056  pop         rbx  
00000057  rep ret          
00000059  push        rbx  
0000005a  push        rbp  
0000005b  push        rdi  
0000005c  sub         rsp,30h 
00000060  mov         rbp,qword ptr [rcx+20h] 
00000064  mov         qword ptr [rsp+20h],rbp 
00000069  lea         rbp,[rbp+20h] 
0000006d  lea         rdx,[rbp+8] 
00000071  mov         rcx,qword ptr [rbp+30h] 
00000075  call        FFFFFFFFFF56F3E9 
0000007a  nop              
0000007b  add         rsp,30h 
0000007f  pop         rdi  
00000080  pop         rbp  
00000081  pop         rbx  
00000082  rep ret
+1  A: 

How do you know that an exception isn't being thrown by a subroutine? Try wrapping it all in a try/catch.

ChrisW
There is nothing between the "Was here" line and the return statement that can throw an exception - and if there was it would cause the program to crash (I tried throwing an Exception to make sure).
Morten Christiansen
A: 

What happens in the calling method after the Trace executes?

If the answer is, as I expect, "nothing", this is almost certainly a threading problem. Either your thread is getting locked at the same point each time (unlikely) or the method you're calling from is being co-opted or blocked between adding the method to the stack and retrieving the return value from same.

Jekke
With regards to threading, there are two threads - a worker thread which does all the work and the main program thread which just waits for the worker to complete all its work (using Join()). Other threads would hae to be some hidden thread work by .NET though I can't see what it should be.
Morten Christiansen
A: 

Did you try to to debug your application? Step into the code and see what happens.

empi
Yes, I'm debugging the app. After the "Was here" line gets executed, the execution just seems to leave the method and continue after the method at the call site.
Morten Christiansen
@Morten What does hitPrimitive look like inside the method after hitPrimitive = _spatialStructure.GetClosestIntersectionPrimitive(ray, ref distance, out collisionResult); is called?
Joseph
Do you use step into or step over? What is the call stack after the execution leaves your method? Moreover, if you leave the method there must some kind of result that you got from it - what is the result value?
empi
@Joseph - thanx for asking that, it led me to find the bug described in my second update. Now the code works but the return statement never has its break point triggered.
Morten Christiansen
+1  A: 

The moral of the story is, if you ask "Is this a bug in {.NET, C#, Windows}", then the answer is probably "No". Millions and millions of people use these things, so the chance of you being the one to find the bug are pretty small - even if there was a bug, someone else will have found it first.

The exception would be a case where you are one of the few people in the world who could have experienced the bug. That makes it more likely you've found it. This could be because you're using a beta, or because you're working in some obscure corner of the software.

But a lot of people would have seen a bug with "return statement never executed". Since you're not likely to be the first to see this bug, you're not likely to have encountered a bug at all.

Thanks to the man who told me that I had not, in fact, found a bug in the TOPS-10 Operating System, some few years ago

John Saunders
I kinda had a feeling that it would turn out this way, but I didn't know what else to do. Anyways, I learned some useful things about how to approach debugging and got my problem solved so it was well worth it.
Morten Christiansen