OnSwipe redirect code

Showing posts with label Visual Studio. Show all posts
Showing posts with label Visual Studio. Show all posts

Tuesday, December 11, 2007

Calling Conventions

This is the outcome of today's presentation by Anand - our tech lead.
There are four calling conventions, and the Microsoft terminologies for them are:
  1. __stdcall
  2. __cdecl
  3. __thiscall
  4. __fastcall
As its known, the calling conventions will tell who, amongst the caller and callee, will clear the parameters from the top of the stack when the function call completes.

__cdecl is the old 'C' way where the stack is cleared by the calling function. Clearing the stack is nothing but having a statement to move the stack pointer up by some number (which is generally the number of arguments). So when a call is placed, immediately after instruction to call, there will be an instruction to move the stack pointer. This way we have an extra instruction associated with every function call instruction. This leads to the increased size of the executable, because of one extra instruction for every function call.

__stdcall is the new way where every function is responsible for clearing the stack allocations made for its parameters. As in, the callee is the one who will rewind the stack and move the stack pointer. In this approach before the return statement of the function a statement to move the stack pointer is introduced. This way the number of instructions will not increase with the number of the function calls.

__thiscall is the object-oriented way of calling functions. Here the first parameter passed is always the "this" pointer. So any instance function member of a class will follow this calling convention. Unlike other parameters, which go to the stack top, the "this" parameter which is also passed is stored in "ECX" register. Now this is how the "this" pointer is implicitly available to all the instance member functions. No function can be explicitly qualified with this calling convention. Any instance member function will get this implicitly, but it can be over-ridden with any other calling convention.

__fastcall is an approach where in the system will try to push the parameters on to Registers instead of the stack just to get a performance boost. But as with the variable qualifier "register" , if the registers are not available then again stack is used for the parameters.

There are a couple of other posts regarding the specifics of the calling conventions and comparison. If this post made any sense then check out those also.

Thursday, November 29, 2007

Intellisense in VS2005 stops working

Its a very well known issue with VS2005. Intellisense is not all intelligent, though it is programmed to be like that. It is indeed helpful and helps us avoid a lot of dog work and remember the big long names and types and parameters a function takes and all that regular crap. But the bad thing is that, the intellisense works fine for the first few days until we get addicted to it and one fine day when you are close to your deadline it suddenly stops working crippling you like anything and your work almost comes to a halt.

Thank god for editors like Vim and build systems which use "Make" and other command line tools. These keep our mind fit enough to do some exercise in case of emergency. Nevertheless we still want that intellisense thing to work, because we have this "IDE" here and it must be better than any editor. So here is how you get it working again:

  • Close the solution.
  • Go to the directory of the solution and delete the .ncb file.
  • Re-open the solution and build it once. The .ncb file must be regenerated now. This must wake up intellisense again and get it working.
  • If not then delete the obj directory of the project also and then build it again.
If none of these work then there is some serious problem that you should not try solving and stop reading this blog and read something useful.


Sunday, November 25, 2007

VS2005 has a feature (supposedly) called "Copy Local"

VS2005 and .NET users are pretty familiar with the way the IDE makes the job so easy and keeps us away from all the build related things like references, linking and all that stuff. But in many cases this might actually be far from desired behavior. One such that recently took away some of my time was the "Copy Local" attribute on the references. This is a boolean property on the references added to a project. If this is set to true, then when the project is built the assemblies added as references as copied to the 'bin" folder of that project. Depending on the build, its either the "Debug" or the "Release" folder. With this, in future whenever the project is built, the DLLs in the bin directory are used, unless you change your references. This will cause a problem when one of the referred assembly is updated and you expect the new behavior, but get the old one instead.

Example, You would have added an assembly, E:\assemblies\MyAssembly.dll as a reference. Now when you want to update the assembly you typically replace the old MyAssembly.dll with the new DLL in the above mentioned location. And then you expect your project to reflect the new assembly, but it does not do that because "Copy Local" being true would have lead to the old DLL being copied to the bin folder of the project and though you updated the DLL in its original location, the reference was pointing to the DLL copied to the bin directory.

So watch out for this Feature. From what I know, this feature can be serialized in the assembly itself. Though this might be a good feature for applications which will use the same DLLs for a long time, this is clearly a bad choice for people who are writing small test applications to test their DLLs. Because with every new build the DLL version changes and yet the references point to the old one.


Friday, November 23, 2007

.NET GAC --- CompileTime v/s Runtime synchronization

GAC - Global Assembly Cache is just a run-time thing.

People familiar with .NET will surely know about GAC. Its just a one stop for any application running on the .NET framework to look for the assemblies (DLLs). When ever we run any .NET application, the framework will look for the referenced assemblies in the GAC. Note that even the version number of the DLL must match. If the application was compiled with an assembly 'A' of version 1.0 and you currently have anything, but 1.0, the application will not run. It needs exactly what it was compiled with. And the best part is that multiple versions can co-exist in the GAC

But this GAC look up happens only at the run-time. In Visual Studio, we will add the required assemblies for a project under the project references. These references will be pointing to the locations where the assemblies are present on the file-system and may be remote locations in case of web references. When we build the project the compiler will look at these locations and not in the GAC. Now if you are referencing an older assembly but we have a newer version in the GAC, then the project will compile but not run. Because at run-time the framework will look for the older assembly but does not find it in the GAC. So be sure of updating your references when your assembly of a particular version in the GAC is updated or replaced by an assembly of a different version.

This problem becomes still more evident and a little tricky when we are using an assembly(say assembly 'A') which again depends on another assembly (say assembly 'B'). And in such a case the problem can become evident even before compilation itself(If the assembly 'B' is related to designer of the Visual Studio). Say assembly A-1.0 was built using assembly B-1.0. Now when we use assembly 'A' by adding it as a reference to our project we are using assembly 'A-1.0' that was built using assembly 'B-1.0'. 'B' does not come into picture during compilation at all. When we build our project and run it, the framework looks for 'A-1.0' and finds out that it needs 'B-1.0' and finds both in GAC and runs the application. Here as 'B' does not come into picture during compilation, it is sufficient if we have it GAC, where as 'A-1.0' has to be at some location on the file system (either local or remote).

Now if 'B' in the GAC is updated, i.e 'B-1.0' is replaced by something like 'B-1.1', and you try to run the previously built application, it fails. Though the assembly referred by you , 'A-1.0' has not changed, the assembly 'B' which is necessary for 'A' has changed. So at runtime the .NET framework will search GAC and the current-folder for 'B-1.0' and as it would not be found, the application fails.

There are a couple of other posts about GAC and references in VS2005. Look out for those.