I read about MSPDBSRV.exe the other day for one of my cases. I found it interesting and thought of sharing it with you.
Here is how things work. The Visual Studio uses MSPDBSRV.exe to generate the symbols (PDB files). All the requests related to creating, accessing or writing to PDB files are handled by mspdbsrv.exe. When a process issues a PDB request and mspdbsrv.exe is not alive, that process will spawn mspdbsrv.exe; but if mspdbsrv.exe is already alive, the living mspdbsrv.exe process will be used and no new process of mspdbsrv.exe will be spawned.
Sometimes it is possible that mspdbsrv.exe stays alive even after the build is over. In such scenarios, it is safe to add a post build event to kill the mspdbsrv.exe. For more information on post-build events, you can check this MSDN document.
Hope you found this small and informative enough (I know nobody likes to read long endless blogs)! Will try to be alive in MSDN blogs from now on. See you all.
Hi there! Recently I remembered that I had an MSDN blog also which I haven't updated since ages! Let me add an interesting issue which I saw recently:
The following code results in different output when built and run from Visual Studio 2003 and Visual Studio 2008:
Code
=====================
#include <stdio.h>
void main()
{
float SinglePrecisionValue;
long result;
SinglePrecisionValue = 3.40282535e+37;
result = (long)SinglePrecisionValue ;
printf("%ld\n", result);
}
Output
=========================
1. Result from VS2003: 0
2. Result from VS2008: -2147483648
So what is happening here? The code tries to convert a float value to long. So why are we getting different values from different compilers?
The C++ Standard says:
An rvalue of a floating point type can be converted to an rvalue of an integer type. The conversion truncates; that is, the fractional part is discarded. The behavior is undefined if the truncated value cannot be represented in the destination type.
Results are incompatible only in cases where program behavior is undefined according to C/C++ Standards. The conversion from Float to int is backward compatible till everything is according to the C++ standards. The problem happens only when truncated value cannot be represented in the destination type. This is the case here. So both the results are expected. We cannot expect undefined behavior to result in same output from two different compilers!
Hey Folks, my team at Microsoft (Developer Support VC++ & C#) has come up with a blog. It will mostly have posts related to issues faced by developers and the troubleshooting steps or methods to analyze and resolve those .
Check this out: http://blogs.msdn.com/dsvc
Hi Guys! It has been a while since I wrote my last post. I had been very busy last month with all the cases flowing in. Recently I worked on a very tricky issue related to OutOfMemoryException. This blog is about that case.
How to reproduce OutOfMemoryException in this scenario:
Create a managed application in Visual Studio 2008 which reads a large input text file into a string. Then use many instances of System.Text.RegularExpressions.Regex to replace parts of this string one after another. Run this application in a 32 bit or 64 bit machine.
Example code snippet (in C#):
//Read the content of file Test.txt into string abc.
// Let us assume the file test.txt is huge. (around 20 MB)
string path = @"C:\Test.txt";
StreamReader sr = File.OpenText(path);
string strFileContents = sr.ReadToEnd();
string abc = strFileContents;
//Apply Regex objects to replace parts of the huge string
Regex rx1 = new Regex("xyz"); if (rx1.IsMatch(abc)) { abc = rx1.Replace(abc, "XYZ"); }
Regex rx2 = new Regex("xyz1"); if (rx2.IsMatch(abc)) { abc = rx2.Replace(abc, "XYZ1"); }
Regex rx3 = new Regex("xyz2"); if (rx3.IsMatch(abc)) { abc = rx3.Replace(abc, "XYZ2"); }
................................
................................
................................
Run the app and.......
This may throw System.OutOfMemoryException. The Exception details may be the following:
System.OutOfMemoryException was unhandled
Message="Exception of type 'System.OutOfMemoryException' was thrown."
Source="mscorlib"
StackTrace:
at System.String.GetStringForStringBuilder(String value, Int32 startIndex, Int32 length, Int32 capacity)
at System.Text.StringBuilder.GetNewString(String currentString, Int32 requiredLength)
at System.Text.StringBuilder.Append(String value, Int32 startIndex, Int32 count)
at System.Text.RegularExpressions.RegexReplacement.Replace(Regex regex, String input, Int32 count, Int32 startat)
at System.Text.RegularExpressions.Regex.Replace(String input, String replacement, Int32 count, Int32 startat)
at System.Text.RegularExpressions.Regex.Replace(String input, String replacement)
Root Cause:
There are two possible root causes of OutOfMemoryException here:
1) The Garbage collector may not be collecting the Regex objects because they have not left scope.
2) This issue may happen because of the huge size of the string. The Regex.Replace method creates a second string for the replace operation. So at that time a second copy of the really large string will be created, which may cause an OutOfMemoryException.
How to fix it:
1) We should always assume that objects will not be available for Garbage Collection until the reference or root has left scope, regardless of whether it will ever be used again. The runtime cannot be relied upon to always know when an object will not be used again. We have to rely on the language rules with respect to variable scoping, or set objects to null explicitly when they will not be used again.
Example code snippet (in C#):
//Set the Regex objects to null explicitly once they will not be used in the code.
Regex rx1 = new Regex("xyz"); if (rx1.IsMatch(abc)) { abc = rx1.Replace(abc, "XYZ"); }
rx1 = null;
Regex rx2 = new Regex("xyz1"); if (rx2.IsMatch(abc)) { abc = rx2.Replace(abc, "XYZ1"); }
rx2 = null;
Regex rx3 = new Regex("xyz2"); if (rx3.IsMatch(abc)) { abc = rx3.Replace(abc, "XYZ2"); }
rx3 = null;
................................
................................
................................
2) "Chunk-up the data” such that string sizes don’t get too big.
Check these too:
Here comes the second (and last) part of my LINQ presentation. Please check the attachment file. (LINQ - 2.pptx).
Hey friends, I have attched part-one of my LINQ presentation (LINQ-1.pptx) here. LINQ is one of the cool new features in .NET framework 3.5. It allows us to do type-safe query of relational database, XML file and even in-memory tables. In more general terms, it applies to all sources of IEnumerable<T> types.
LINQ uses many new fewtures introduced in .NET Framework 3.5. For e.g.:
- Partial methods
- Local Variable Type Inference.
- Extension methods... (My Favorite!! :))
- Lambda expression.
- Query expression.
- Contextual Keywords, etc...
I have tried to explain these new features in my presentation as without these, LINQ wasn't possible.
ISSUE:
I am back with another mixed-mode situation. An issue may happen when the native class constructor calls a managed function.
For example, Let us say we have a C# application which is calling a C++ DLL using DLL Import attribute. The C++ DLL has a class whose constructor initializes a few variables and also calls a managed function. This may lead to loader lock issue.
CAUSE:
Let us see why this issue may happen. There are two distinct mechanisms for loading an execution module (EXE or DLL):
1) One for Windows, which is used for unmanaged modules,
2) One for the .NET Common Language Runtime (CLR) which loads managed assemblies.
When an assembly containing only .NET constructs is loaded into a process, the CLR loader can perform all of the necessary loading and initialization tasks itself. However, for mixed assemblies, because they can contain native code and data, the Windows loader must also be used.
The Windows loader guarantees that no code can access code or data in that DLL before it has been initialized, and that no code can redundantly load the DLL while it is partially initialized. To do this, the Windows loader uses a process-global critical section (often called the "loader lock") that prevents unsafe access during module initialization.
If we attempt to execute managed functions when this loader lock is held, the CLR will attempt to automatically load the managed assembly, which may require the Windows loader to block on the loader lock. Since the loader lock is already held by code earlier in the call sequence, a deadlock results. However, it is possible that the required managed assembly has already been successfully loaded by other code. In that case, the deadlock will not happen. This makes this scenario difficult to diagnose and fix as the situation does not guarantee that a deadlock will happen.
RESOLUTION:
So to avoid this problem, we should make sure that the native constructor doesn’t have any managed function call. We can call that managed function outside the constructor which lets the native DLL to get initialized successfully.
Thumb Rule:
Do NOT call a managed function in constructor of an unmanaged class.
A few definitions to start with:
Managed code: Code executing under the control of the CLR is called managed code. For example, any code written in C# or Visual Basic .NET is managed code.
Unmanaged code: Code that runs outside the CLR is referred to as "unmanaged code." COM components, ActiveX components, and Win32 API functions are examples of unmanaged code.
Users may have a mixed-mode application where a managed code is accessing an unmanaged code or vice-versa. There are three technologies which enable managed/unmanaged interaction:
1) Platform Invoke (P/Invoke)
2) COM Interop
3) C++ Interop (IJW)
I am writing about the third technology here. We should use C++ interop for wrapping complex unmanaged flat APIs, or for wrapping unmanaged flat APIs that are changing while managed code is under development. C++ interop allows direct access to unmanaged APIs—which requires no rewriting, just the inclusion of a header file. The wrapper is compiled using /clr compiler switch which generates mixed-mode native/managed output.
The header of native C++ code is included in the managed wrapper. This causes the native C++ code to get compiled as managed code. Sometimes this may cause problems.
One of such problems may happen when the application has some static or global objects. The life time of such objects is until module unloading happens. So these objects are destructed at the end, even after the CLR is shut down. To avoid any error, we should make sure that these objects are purely unmanaged. We should not have any global objects that use .NET. All managed objects should be destroyed before the CLR shuts down.
As I wrote earlier, native code gets compiled as managed when their headers are included in managed code. The native code may have global or static objects which become managed in this way. The destructor of such objects will be called after the CLR is shut down which causes BOOTUP_EXCEPTION_COMPLUS exception to be raised. The application will crash just before it exits.
To solve such issues, we should wrap the include statements of these native header files (which declare classes whoes global objects exist) in the managed C++ code as follows:
//Managed code file
//compile the native file as unmanaged:
#pragma managed(push, off)
#include <xyz.h> //The unmanaged code header.
#pragma managed(pop)
The above wrapper statements cause the compilation of class declared in “xyz.h” as unmanaged. This solves the issue. The application can have a global or static object of this class.