Tuesday, November 4, 2008

DEBUGGING

Introduction to Debugging:

Source code is compiled and run in the .NET Framework using a two-stage process. First, source code is compiled to Microsoft intermediate language (MSIL) code using a .NET Framework–compatible compiler, such as that for Visual Basic .NET or Visual C#. Second, MSIL code is compiled to native code.

Essentially, the process of debugging goes in the reverse direction. As you execute code, the debugger first maps the native code back to MSIL, and then maps the MSIL code back to source code using programmer database (PDB) files. To enable debugging, it is thus necessary to generate the required mapping information at each stage in the compilation process.

The first step of enabling debugging is to create the PDB file that maps MSIL to source code. When developing precompiled components with either Visual Basic .NET or Visual C#, this is specified using the /debug switch. When using code-behind pages in ASP.NET, this is specified with a setting in the computer's or application's .config file.

The second step required for debugging is to instruct the just-in-time (JIT), MSIL to native code compiler to create mapping information between the MSIL and native code. This is accomplished by setting the JITTracking attribute in your assembly. This attribute, which is essentially a flag, is automatically set when a process to be debugged is loaded from within a debugger. However, if the process is loaded (and JIT-compiled) outside the debugger, and the debugger is later attached, it is necessary to set this attribute beforehand using a compiler switch. If this attribute is not set, a debugger attaching to a running program cannot work back from the native code to the MSIL, and it will not be possible to map farther back to the source code in that debugging session.

Whereas Visual Studio .NET can be used for compiling and debugging, it is important to realize that a debugger, such as the CorDbg and DbgClr debuggers included with the .NET Framework SDK, does not compile MSIL code. When using a stand-alone debugger, it is necessary to first compile the code to MSIL using a separate compiler. An important side effect of this process is that if your source code changes while debugging, a simple reload of the source code file will not suffice, and you will need to recompile. ASP.NET, of course, is a special case — code behind ASP.NET pages is actually compiled dynamically by ASP.NET using the command-line compilers in the .NET runtime directory.

Compiler Switches:

Both the Visual C# and Visual Basic .NET compilers support the same set of debug compiler switches. Although there appear to be many possible combinations, only the following three configurations are actually possible.

Do not include debugging information:

(nothing)

/debug-

Create a programmer database (PDB) file:

/debug:pdbonly

Create a PDB file and set the JITTracking attribute:

/debug

/debug+

/debug:full

As mentioned earlier in this tutorial, there are two steps in the compilation and debugging process. When compiling from source code to MSIL, any of the debug switches except /debug- will result in a PDB file being created. Three of the remaining options — specifically, /debug, /debug+, and /debug:full — all do the same thing: they create the PDB file and cause the JITTracking attribute to be set, which allows a debugger to map native code back to source code when the debugger attaches to a running program.

The .NET Framework SDK includes the command-line runtime debugger named CorDbg.exe, which some developers might prefer over its Windows-based counterparts, DbgClr and the debugger that is built into Visual Studio. As with DbgClr, CorDbg does not compile applications. To use these compilers, it is first necessary to build the application so that it includes the appropriate /debug switch.

Using CorDbg u can debug window calc.exe using command line switches.

Source:

http://msdn.microsoft.com/en-us/library/aa719464(VS.71).aspx

http://blogs.msdn.com/tess/archive/2006/04/13/575364.aspx

Don’t run production ASP.NET Applications with debug=”true” enabled:

Imapact of switch on within the application’s web.config file:

Doing so causes a number of non-optimal things to happen including:

  1. The compilation of ASP.NET pages takes longer (since some batch optimizations are disabled)
  2. Code can execute slower (since some additional debug paths are enabled)
  3. Much more memory is used within the application at runtime
  4. Scripts and images downloaded from the WebResources.axd handler are not cached

Others are:

  1. ASP.NET Timeouts
  2. Batch compilation

ASP.NET Timeouts:



When debug is set to true, asp.net requests will not time out. This is to allow you to debug with visual studio at your own pace without having to worry about the requests suddenly disappearing.



Batch compilation :

In debug mode there is no batch compilation means each page is compiled into any assembly. In batch compilation all pages in folder / all user controls etc compiled into single assembly so number of assembly reduced from some 100 to 10.

This not only effect memory footprints
But… and this is a big but… there is overhead for each dll, and if the dll is compiled in debug mode there is overhead for items needed for debugging, and … last but not least (in fact probably most important), the assemblies won’t be laid exactly side by side, so with a large number of assemblies you start fragmenting the virtual address space making it harder and harder to find large enough spaces to store the managed heaps, potentially causing out of memory exceptions.



This last point is particularly important, since it means that all client-javascript libraries and static images that are deployed via WebResources.axd will be continually downloaded by clients on each page view request and not cached locally within the browser.When is set, the WebResource.axd handler will automatically set a long cache policy on resources retrieved via it – so that the resource is only downloaded once to the client and cached there forever (it will also be cached on any intermediate proxy servers).

What about binaries compiled with debug symbols?

Compile assemblies with debug switch for detailed stack trace but set in web config to avoid hit.

The debug symbols and metadata in the compiled assemblies will increase the memory footprint of the application, but this can sometimes be an ok trade-off for more detailed error messages.

To Restrict all application on server overwriting debug setting in web.config set:



The Switch in Maching.config

You will disable the switch, disable the ability to output trace output in a page, and turn off the ability to show detailed error messages remotely. Note that these last two items are security best practices you really want to follow (otherwise hackers can learn a lot more about the internals of your application than you should show them).

There isn’t a ton of documentation on this switch – but you can learn a little more about it here.

Scott's blog

http://blogs.msdn.com/tess/archive/2006/04/13/575364.aspx





Discussion thread:



Publish Web Site always builds non-debug symbols (unless you specify otherwise). But you would still want to turn off debugging in the web.config file for point 4 above.



Your custom errors will work fine with the retail switch set. I think what is disabled is the ability to turn customerrrors off -- meaning the ability to expose the raw exception to remote customers directy (which you want to make sure you never do with a production app).



Good question about the caching. I think the client behavior depends on what your client is configured to-do with the browser. You can select either check for changes always, or just have it set to automatic.



I have an even better reason to not deploy debug code. When you compile in debug mode, the PDB file includes references to the enviroment on which it was compiled. You will note that when an exception gets thrown in code that has debug mode on, it shows you the code that contains the error, as well as the path to the file. This path is always the location where the code was compiled, NOT the location where the code was running from.



More importantly, when an exception is thrown, the CLR tries to retrieve the code "live" from the location containted in the PDB. If you deploy debug code to production, it tries to retrieve the code from your dev server when the exception is thrown. It tries to log in to the dev server. The problem is that it logs into the dev server, using your production credentials (of the aspnet user) Assuming your password is not the same in prod and dev, it fails this authentication. If it gets a few errors in a row (3 on my server) the dev account gets locked out!

Obviously this is only an issue if your prod server has network level connectivity to your

Correct -- the HTTPS protocol doesn't allow caching of resources client-side.





No comments: