For other compiler options refer .Net framework SDK documentation. .NET Debugging
Debugging is the most important feature of any programming language and Visual Studio .NET IDE provides this feature in an effective manner but you can still do pretty good
job with the .NET SDK alone. Application source code goes through two distinct steps before a user can run it. First, the source code is compiled to Microsoft Intermediate
Language MSIL code using a .NET compiler. Then, at runtime, the MSIL code is compiled to native code. When we debug a .NET application, this process works in
reverse. The debugger first maps the native code to the MSIL code. The MSIL code is then mapped back to the source code using the programmers database PDB file. In
order to debug an application, these two mappings must be available to the .NET runtime environment.
To accomplish the mapping between the source code and the MSIL, use thedebug:pdbonly compiler switch to create the PDB file Note: When building
ASP.NET applications, specify the compilation setting debug=true in the application’s Web.config file. The second mapping between the MSIL code and native code is
accomplished by setting the JITTracking attribute in our assembly. By specifying the debug compiler switch, the PDB file is created and the JITTracking attribute is enabled.
When using this compiler switch, a debugger can be attached to an application loaded outside of the debugger.
Once the required mappings exist, there are several means by which to debug our applications. We can use the integrated debugger within Visual Studio .NET, or, if we
prefer, we can use DbgClr, a GUI-based debugger. There is also a command line debugger, CorDBG that is included in the .NET Framework SDK.
3.4 Managed Vs. Unmanaged MethodsTransitions
In .Net Framework CLR provides execution of instruction targeted for CLR and the instructions that are not targeted for CLR. The instructions targeted for CLR are called as
managed code and other type of code is called unmanaged code. After going through this topic you will know the following things mentioned below
Difference between Managed Method and Unmanaged Method. Difference between Managed Type and Unmanaged Type.
How to call unmanaged methods in managed methods. How to use unmanaged types.
When an application is launched for execution, first request is given to the Operating System, the OS will load the executable file in memory and starts executing the
instruction from the entry point function in the executable file. Where in .NET executable file contains four main components the CLR header, the Metadata, the MSIL Code, and
Native code. CLR header will be used by the managed code in the module which will have the version
number of the CLR on which the module is built and entry point method of the module in the executable.
Metadata describes the types used in the managed code, combination of CLR header and MSIL Code is the compiled format of a .Net language on a .Net Compiler, which will not
have the instruction in targeted machine instruction format, which will again get compiled by the JIT Compiler
Native Code contains the machine instruction, which will be directly executed by the OS. Not all the .NET PE will have the Native code. PE of type EXE’s will be having a native
method like main called as “unmanaged stub” which will be an entry point for the OS to execute code, that function will jump to _CorExeMain function located in MSCoree.dll
which will be executed by the OS to initialize CLR and attach the running .NET module to CLR. Once CLR is initialized and loaded CLR will start executing the assembly by
executing the managed entry point function specified in the CLR header of the file. Managed Code
Machine instructions in MSIL format and located in Assemblies will be executed by the CLR, will have the following intrinsic advantages,
Memory management to prevent memory leaks in the program code,
•
Thread execution,
•
Code safety verification,
•
Compilation, Executed on many platforms like Windows 95, Windows 98, Windows 2000,and other
system services.
Managed methods will be marked as “cil” in MSIL code. Methods marked with “cil” will be compiled by mscorjit.dll before execution. C and VB.NET will generate only
managed code. Managed C++ can generate managed code by specifying “pragma managed”
Unmanaged Code Unmanaged codes are the instructions, which are targeted for specific platforms.
Unmanaged code will exist in any of the format, A code instructions in managed C++ with “pragma unmanaged”
COMCOM+ Components
Win32 DllsSystem Dlls As these codes are in native format of OS, these instructions will be executed faster
compared with JIT compilation and execution of Managed code. Managed and Unmanaged transitions
As we get more benefits from managed code, still we may need to use unmanaged code. .Net provides many ways to access unmanaged code in managed code. Managed-
Unmanaged transitions are achieved in .Net by set of services called Platform Invocation Services PInvoke and IJWIt Just Works.
PInvoke services are targeted for unmanaged code, which exists as COMCOM+ components and Win32 DLLs. COMCOM+ components will accessed by the concept
called COM Interop - is a mechanism in which existing COM components will be accessed through a wrapper class called COM Callable Wrapper CCW in managed code
without modifying the existing COM components. Using PInvoke mechanism we can call Windows DLL functions in managed code.
IJWIt Just Works targets code instructions built on C++ managed extensions, This mechanism is only for the code in Managed C++. In this way we can call the unmanaged
methods directly by the managed code.
For example following code calls the MessageBox function in User32.dllVB.NET Imports
System.Runtime.InteropServices Public
Class Win32
Declare Auto
Function MessageBox
Lib user32.dll
ByVal hWnd
As Integer
, _ ByVal
txt As
String ,
ByVal caption
As String
, ByVal
Typ As
Integer As
Integer End
Class Module
Module1 Sub
Main Win32.MessageBox0, Hello world , Temp path
is, 0 End
Sub End
Module
Declare is the statement to state the Win32 API functions located in the Win32 DLLs. And the respective arguments declared with CLR data type.
In C, we need to use the extern keyword with the attribute DLL Import to specify the Win32 DLL and the function should be declared as static function.
using System;
class PInvokeDemo
{ [dllimportuser32.dll]
public static
extern int
MessageBox int
hwnd, string
msg, string
caption, int
type; public
static int
Main {
MessageBox0, Hello World, Tutorial, 1; return
0; }
} In the above example MessageBox function is accessed from user32.dll by using the
attribute DLL Import, and declared as static function Managed Types and Unmanaged Types
We have seen how to call an unmanaged code in a managed code, now the question is how unmanaged code understands the managed data type and vice the versa. We will see
how string will be sent from managed code and returned back to managed code. When passing a string value as an input argument to an unmanaged code CLR will take care of
converting that to a native string type. When we try to call a function, which returns string then the managed code, has to
allocate memory and send to the function in unmanaged code. For example if we want to retrieve the OS Temp path then we can call GetTempPath API function of “kernel32.dll”,
Following code snippet shows how to call the function with string as an out argument with VB.NET.
Imports System.Runtime.InteropServices
Public Class
Win32 Declare
Auto Function
MessageBox Lib
user32.dll ByVal
hWnd As
Integer , _
ByVal txt
As String
, ByVal
caption As
String ,
ByVal Typ
As Integer
As Integer
Declare Auto
Function GetTempPath
Lib kernel32.dll
ByVal lenOfChar
As Integer
, ByVal
strData As
System.Text.StringBuilder As
Integer End
Class Module
Module1 Sub
Main Dim
l As
Integer Dim
data As
String Dim
tempPath As
System.Text.StringBuilder = New
System.Text.StringBuilder255 l = 255
Win32.GetTempPathl, tempPath Win32.MessageBox0, tempPath.ToString, Temp path
is, 0 End
Sub End
Module
Following code snippet shows how to call the function with string as an out argument with C.
using System;
using System.Text;
class PInvokeDemo
{ [ dllimportkernel32 ]
public static
extern int
GetTempPath int
size, StringBuilder buf ;
public static
int Main
{ const
int size = 255;
StringBuilder tempPath
= new
StringBuilder size ;
GetTempPath size, tempPath ; System.Console.WriteLine tempPath ;
return 0;
} }
The above code uses StringBuilder class of System.Text namespace to allocate string with 255 characters Just think for this as a fixed string we used to have in VB.
Some of the functions in managed code will be accepting arguments as structures, structures in unmanaged code will be having set of member fields located in memory as
the order in which it has been declared, that is the layout of member variable location is fixed. But in .Net, structures will have fields of managed data type and these member
fields will automatically change the memory location of the structure. CLR will automatically move the data members to improve memory usage and performance.
When an unmanaged method, which expects an argument as a structure, then managed code has to declare the structure so that it can be accessed by the unmanaged code. But
.NET structures will have auto memory layout of data members, so to pass structures from managed code to unmanaged code has to be declared with an attribute StructLayout
in System.Runtime.InteropServices namespace. StructLayout is used with an enumerated value LayoutKind with following options given
below:
•
Auto – default option which changes the member field memory layout.
•
Sequential - specifies member variable should be placed in a sequential order as specified while declaring the type.
•
Explicit- specifies the exact location of the member variable in the structure.
3.5 Summary