tags:

views:

1545

answers:

10

After deploying our huge distributed system to one of our clients we experience an unexpected error. During the investigation we replace the assembly causing the error with one where we have added some diagnostic code. The dll we use is built in debug mode. And suddenly it all works!

Replacing the debug dll with the release version (with the diagnostic code) makes it crash again.

There are no precompiler directives, conditional debug attributes etc. in our code. The problem has been found in two different installation sites, while it works fine in several more.

(The project has a mix of C# and VB.NET, the troublesom assembly is VB.NET.., if that makes any difference)

So the question is: What do you do in situations like this? And what can be the cause - in general? Any advice on debugging this issue is welcome.

+7  A: 

For causes... well, some hint of the symptom would help. One possibility is that you have code to a method like Debug.WriteLine that has side effects (i.e. makes it work). Calls to methods marked with [Conditional(...)] are not compiled unless you have the right symbols defined - so anything marked [Conditional("DEBUG")] will be silently dropped.

It could also be a compiler bug, but that is a bit unlikely (but not impossible).

What is the symptom? How does it break?

As an example of the above:

    static string Bar { get; set; }
    static void Main()
    {
        Bar = "I'm broken";
        Debug.WriteLine(Foo());
        Console.WriteLine(Bar);
    }
    // note Foo only called in DEBUG builds
    static string Foo()
    {
        Bar = "I'm working";
        return "mwahahah";
    }

Compiled in DEBUG mode it prints "I'm working"; compiled in RELEASE mode it prints "I'm broken". Does this sound similar? Check you aren't calling any debug methods directly with things that have side-effects. In most cases, you can fix by indirection:

string foo = Foo();
Debug.WriteLine(foo);

Now it gets called in either mode.

Marc Gravell
As I said, I don't think there are any precompiler directives, conditional debug attributes etc. in our code. Same goes for Debug.WriteLine. But more investigation is needed.
Torbjørn
+2  A: 

There are some good pointers here

Paul Nearney
+2  A: 

You can try and turn off Optimize Code in the Build Settings. What is the actual error you are getting.

Another thing you can do is compile in release mode but enable the #Debug conditional. This will handle the case if your using Diagnostics.Debug and the code in there effects your application.

JoshBerke
+3  A: 
Debug.Assert(ImportantMethod() == true);
Ed Guiness
Another very good [Conditional(...)] example.
Marc Gravell
+2  A: 

It might be some sort of race condition you have, if you're not working in single-threaded code. For example, if some part of your program needs to perform some actions before other parts can access it, it might fail in release mode simply because the code is accessed too early. We once had a similar problem with some code for mobile phones which ran fine in the emulator but on the phone which was slower, the sitution was not the same at all.

Morten Christiansen
+2  A: 

Have you tried including the debug files? (the pdbs)

If you co go your project settings and then the compile 'tab' select your release build in the dropdown near the top, then choose advanced compile options near the bottom, make sure to set it to create FULL debug information, then redeploy, you should now get more detailed information about the reason for the crash.

Brian Schmitt
+2  A: 

I've seen timing which cause issues between Debug and Release build. Generally Debug build runs slower than Release build. You might want to check time critical section of your code.

faulty
A: 

You probably know this, but, variables are sometimes initialised differently in debug and release builds. E.g. I think variables are auto-init'd in VC6 debug builds, this can hide problems if you didn't initialise something. I also think debug arrays may use sentry bytes in an attempt to indicate overruns. This too can lead to different behaviour.

Cokes
I'd +1 if the questioner hadn't indicated that they were using managed code. 9 times out of 10 when I've had a problem like this, it's been in c++ and it was because I forgot to init something properly in the .ctor. Fortunately for me, none of those mistakes have ever made it into production.
Greg D
A: 

I have a similar problem. My situation like this: I defined some reflection functions in a class library A. Then I defined a WPF user control library B, which uses the functions from library A. Then I coded an application which uses the user control from library B and functions in library A. When I used the debug version of library B, it works fine. But when I used the release version of library B, the reflection functions did not work. I also defined other functions in library A. It seems that only reflection functions are causing trouble. I can not figure out the reason. Finally, I gave up and moved the reflection functions from library A to library B. And it worked.

A: 

I had a problem at one point with finalizers going off sooner than expected, because I didn't fully understand the interplay between finalizers, the garbage collector, and when a local object is considered collectible (hint: it's not at the closing curly brace of the block). If your code uses finalizers, you may wish to look into GC.KeepAlive(). In the following block:

void MyFunction() 
{ 
  Foo f = new Foo();
  SomeFunction(f.SomeProp);
}

f becomes eligible for finalization before SomeFunction() even runs! If the finalizer does something like dispose whatever SomeProp hands out, you could get into trouble. Adding a call to GC.KeepAlive(f) after the call to SomeFunction ensures that f isn't eligible for finalization until after the call to KeepAlive().

Edit: After all that, I forgot to point out that this problem was much more pronounced when running in Release mode. I don't know if the Debug build puts implicit KeepAlives for locals at the end of the function for the debugger's benefit, or if the garbage collection is simply less aggressive, or what, but Release mode exacerbated this problem greatly in my case.

twon33