Welcome to MSDN Blogs Sign in | Join | Help
Objects and Properties - The C# 3.0ish way!!

These days I have been bitten by the C# bug. As most would agree, the effects are "addictive". Migrating from one to Language to another has always been like shifting homes, which you wouldn't do unless forced to. But the .NET/C# team is ensuring that this "migrating" is something that everyone would want to do.

In my latest quest for writing a "Files and Folder Sync" application, I discovered some cool new features, that swiped away the earth below my feet. My application has a simple class called CFolderSync, with 6 members. I want to have Read-Write properties for these members. So this is how I would do that in traditional way

<Code Snippet - CFolderSync in Traditional way>

public class cFolderSync
        {
            private bool bFolderLocation1Validated;
            private bool bFolderLocation2Validated;

            private string sPrimaryLocation;
            private string sSecondaryLocation;

            private DirectoryInfo dirInfoLocn1;
            private DirectoryInfo dirInfoLocn2;

            public bool bFolderLocation1Validated 
                    {
                        get{return bFolderLocation1Validated;}
                        set{bFolderLocation1Validated=value;}
                    }

           public bool bFolderLocation2Validated 
                  {
                      get{return bFolderLocation2Validated;}
                      set{bFolderLocation2Validated=value;}
                  }

          public string sPrimaryLocation
                 {
                     get{return sPrimaryLocation;}
                     set{sPrimaryLocation=value;}
                 }

          public string sSecondaryLocation
                {
                    get{return sSecondaryLocation;}
                    set{sSecondaryLocation=value;}
                }

         public DirectoryInfo dirInfoLocn1
               {
                   get{return dirInfoLocn1;}
                   set{dirInfoLocn1=value;}
               }

         public DirectoryInfo dirInfoLocn2 
              {
                  get{return dirInfoLocn2;}
                  set{dirInfoLocn2=value;}
              }

</Code Snippet>

As you can see here, I am simply trying to "establish" properties for the Private fields. Nothing fancy here. In fact most often than not that's all we want and we have in the Get and Set. In C# 3.0+ we can achieve the same in much more cleanly manner

<Code Snippet - cFolderSync the C# 3.0 way>

public class cFolderSync
        {
            public bool bFolderLocation1Validated { get; set; }
            public bool bFolderLocation2Validated { get; set; }

            public string sPrimaryLocation { get; set; }
            public string sSecondaryLocation { get; set; }

            public DirectoryInfo dirInfoLocn1 { get; set; }
            public DirectoryInfo dirInfoLocn2 { get; set; }

            //Using the Auto Getter and Setter enhancement in .NET 3.5
        }

</Code Snippet>

So we see even though we imply "public", but the moment we get this empty get and set, Compiler (.NET engine some would say) makes the necessary arrangements to make the member as private and the get and set property as public. That's why we call this as Auto Getter and Auto Setter.

This is only one side of the coin. Given the above Class, how do we plan to initialize an instance of this object...

<Code Snippet - Object Initialization the C# 3.0 way>

cFolderSync oFolderSync = new cFolderSync
        {
            bFolderLocation1Validated = false,
            bFolderLocation2Validated = false,
            sPrimaryLocation = string.Empty,
            sSecondaryLocation = string.Empty,
            dirInfoLocn1 = null,
            dirInfoLocn2 = null
        };

</Code Snippet>

The most interesting part is how the Intellisense works...

image

...

...

image

...

...

image

We can see how intelligent our intellisense is. It only displays the members which are yet to be analyzed. The only problem I faced with the Auto Getter and Setter  was that, if I want to have a Read-Only or Write-Only property, we simply cannot do a {get;} or {set;} respectively. But that doesn't mean we cannot have Read-Only or Write-only property. We can do the following..

{get; private set;}

Then we use constructors to initialize the objects. More reading recommended

Auto Implemented Properties: http://msdn.microsoft.com/en-us/library/bb384054.aspx

Implementing Immutable Class having Auto Implemented Properties:

http://msdn.microsoft.com/en-us/library/bb383979.aspx

I hope you enjoyed this blog. Enjoy the .NET 3.5ish way;

Slang - 'C' - Lang (for beginners)

Hello Guys,

Sorry again if the title is misleading, but how often pointers have been more like a slang to a beginner. I can bet there are more nods right now!! I am middle of studying deeper into Templates, but I just found enough time to talk about Pointers (and constants).

This is supposed to be a small topic and I promise to keep it that way.Lets start right away..

int const *x;
int * const x;

Lets break it and lemme(did I use sms language) show you how to interpret that..

Block A-----Block B------Block C-----Block D
    int           const      *(pointer)        x

    int         *(pointer)      const          x

 

Reading sequence would be Block D->Block C-> Block B-> Block A

Let me show you what I am trying to say.

1) x(starting from Block D) is a pointer (now in Block C) to a constant (moving to Block B) int (moving back to Block A)

Lets go in the same way for second one..

2) Remember, we would start from Block D, jump to Block C move to  Block B and then move to Block A..so lets start.

x is a constant Pointer to an int.

 

Great, now that we have learnt how to read this, lets see what these actually mean...

1) Let me repeat "Constant pointer to int". Now looks relatively simpler, isint it? 

  1. Pointer is of type int
  2. Constant pointer, so the address it is referencing, cannot be changed (the value its pointing to can be changed). 

2) "Pointer to constant int"

  1. Pointer is pointing to int
  2. Its a pointer to a constant value. So the value that address is pointing to, cannot be changed (the address itself can be changed).

 

I hope now pointers and constants make more sense to you. Please do leave comments. If I sneak once more, I would edit this and add some coding examples. Good bye till then.

Function Calls and the conventions - Steps towards effective debugging

Hello Guys,

How often has it happened, that we do things without really knowing why we are doing so. I can hear you speaking to yourself... Its not a fault (or a "trap" :P ). Many a times we end up doing that, since most often, the work needs to be completed, period. Learning a certain thing (a big thing), is often like solving puzzles. Its only when you have put all the pieces together, you know the importance of a certain piece.

Debugging is one such puzzle. Function calling conventions - one of those pieces. Today I would talk about function calling conventions that are available to us. Its those basics again(for veterans), nothing new or exiting...but come on, these things never hurt. This time I am covering only Function calling conventions.

N.B - The examples (if any) will reference C/C++ (C# at most). Generally (and I mean GENERALLY) when we use functions we do not use any "specifier" explicitly for calling conventions.

Let's first discuss about the Function Calling Conventions available. We will talk about some that are still alive (__pascal, __fortran,__syscall -> R.I.P).

  • __cdecl
  • __stdcall
  • __fastcall 
  • __thiscall

Calling conventions mainly..

  • decide the way/order things are pushed to the Stack
  • who is going to clean the mess (clear the stack I meant)

The first point is important because, the parameters are accessed by EBP's, in the manner of [EBP + 8], [EBP + 12], etc..(we will talk about stacks later someday, another point to remember here is EBP is used for stack walking when optimization like FPO is not used, else ESP is used directly.)

The second point is also very important because in Static functions (static in terms of number of parameters being constant), the called function (Callee) has complete idea about the number of parameters being passed to it on a particular call, because that is stagnant. Once it has the complete idea, it can do the cleaning stuff.

But in case of dynamic functions (wondering about dynamic functions...hmm...printf(), If you want to write your own, you can use <stdarg.h>/<cstdarg> .)only the calling function knows about the number of parameters that is getting passed. So the onus is on the Calling function. We could have had made the called functions do the cleaning, but we have to pass much more information(infact store them) so that the Callee can use them to cleanup. Which is an obvious overhead that is not economic.

Calling conventions, where the Calling functions do the cleanup, are usually less efficient than the function calls where the Callee function do the cleanup. The executables are also larger in size. Remember that, if we had to pass and store the extra information on Dynamic functions so that the Callee can cleanup, the executable would have been even larger in size.

Function calling convention also decide the way function names are decorated(mangled). I won't talk here much about name mangling because thats another topic. I could have shown some examples but in VS2008, nor in Windbg the proper mangled names are displayed. Just to remember that Name Mangling (Name Decoration as also known) is also dependent on the Calling convention. Those are quite simple in C but quite tricky in C++ (refer to http://en.wikipedia.org/wiki/Name_mangling for the Name Mangling).

Now lets explore each convention mentioned above.

__cdecl
=-=-=-=-

  • Parameters are passed from right to left ( int foo (int _a, int _b, int _c), here they are pushed to stack in the following order _c -> _b -> _a )
  • The calling function has to do the cleanup.
  • Its default calling convention for C/C++ (In case of C++ its default if we are not calling Member Functions or Member Functions have dynamic number of parameters)
  • Larger executables.
  • From compiler, the option is to compile using /Gd

<code>
void __cdecl pf(int a,int b)
{
}

int main()
{
 int a=5,b;
 b=a+1;
 pf(b,a);
 return 0;
}
<\code>

For this convention the mangled name would be ?pf@@YAXHH@Z

If you have VS installed, search for undname.exe (utility for undecorating names), then you can do the following..

D:\VS2008\VC\bin>undname ?pf@@YAXHH@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?pf@@YAXHH@Z"
is :- "void __cdecl pf(int,int)"

If you view the diassembly, you will see that RET (which is the return command) is without any operands/parameters. This is because in this calling convention the callee dosent cleanup the stack. Look at the last opcode

<DISASSEMBLY>
void __cdecl pf(int a,int b)
{
001113A0 push ebp
001113A1 mov ebp,esp
001113A3 sub esp,0C0h
001113A9 push ebx
001113AA push esi
001113AB push edi
001113AC lea edi,[ebp-0C0h]
001113B2 mov ecx,30h
001113B7 mov eax,0CCCCCCCCh
001113BC rep stos dword ptr es:[edi]
}
001113BE pop edi
001113BF pop esi
001113C0 pop ebx
001113C1 mov esp,ebp
001113C3 pop ebp
001113C4 ret
<DISASSEMBLY>

__stdcall
=-=-=-=-=

  • Windows programmers are so much used to this. This is used everywhere in Windows Programming. Actually the name used there is WINAPI(you can say it as synonym for __stdcall).
  • Parameters pushed into stack from right to left. The this parameter of objects are passed to stack at last.
  • Stack cleared up by Callee function.
  • From compiler, the option is to compile using /Gz

<code>
void __stdcall pf(int a,int b)
{
}

int main()
{
 int a=5,b;
 b=a+1;
 pf(b,a);
 return 0;
}
<\code>

For this convention the mangled name would be ?pf@@YGXHH@Z

D:\VS2008\VC\bin>undname ?pf@@YGXHH@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?pf@@YGXHH@Z"
is :- "void __stdcall pf(int,int)"

So since in case of __stdcall the stack is cleared up by the callee, you would see in the disassembly that the RET is followed by the size of all the parameters. In this case, it would be 4 bytes of int a + 4bytes of int b. If there was a double c, you would see RET 10h (remember this 10 is in hex so its decimal equivalent would be 12)

<DISASSEMBLY>
void __stdcall pf(int a,int b)
{
003C13A0 push ebp
003C13A1 mov ebp,esp
003C13A3 sub esp,0C0h
003C13A9 push ebx
003C13AA push esi
003C13AB push edi
003C13AC lea edi,[ebp-0C0h]
003C13B2 mov ecx,30h
003C13B7 mov eax,0CCCCCCCCh
003C13BC rep stos dword ptr es:[edi]
}
003C13BE pop edi
003C13BF pop esi
003C13C0 pop ebx
003C13C1 mov esp,ebp
003C13C3 pop ebp
003C13C4 ret 8
<DISASSEMBLY>

__fastcall
=-=-=-=-=

  • The main essense is that , the first two parameters if are equal to or less than 32 bits (like int) are pushed to the ECX and EDX registers. Rest are pushed to stack. Since operations are registers are faster, hence the name __fastcall.
  • Parameters which are not pushed to Registers are pushed from Right to left.
  • The Called function clears the stack, which obviously means that __fastcall becomes incompatible with function with dynamic arguments.
  • From compiler, the option is to compile using /Gr

<code>
void __fastcall pf(int a,int b)
{
}

int main()
{
 int a=5,b;
 b=a+1;
 pf(b,a);
 return 0;
}
<\code>

For this convention the mangled name would be ?pf@@YIXHH@Z

D:\VS2008\VC\bin>undname ?pf@@YIXHH@Z
Microsoft (R) C++ Name Undecorator
Copyright (C) Microsoft Corporation. All rights reserved.

Undecoration of :- "?pf@@YIXHH@Z"
is :- "void __fastcall pf(int,int,int)"

Now lets have a look at the disassembly

<DISASSEMBLY>
void __fastcall pf(int a,int b)
{
000413A0 push ebp
000413A1 mov ebp,esp
000413A3 sub esp,0D8h
000413A9 push ebx
000413AA push esi
000413AB push edi
000413AC push ecx
000413AD lea edi,[ebp-0D8h]
000413B3 mov ecx,36h
000413B8 mov eax,0CCCCCCCCh
000413BD rep stos dword ptr es:[edi]
000413BF pop ecx
000413C0 mov dword ptr [ebp-14h],edx
000413C3 mov dword ptr [ebp-8],ecx
}
000413C6 pop edi
000413C7 pop esi
000413C8 pop ebx
000413C9 mov esp,ebp
000413CB pop ebp
000413CC ret
<DISASSEMBLY>

Ok this is strange, we see simply ret. But isint that in __fastcall, the callee is supposed to clear the stack. Yes you are correct, but lets revisit the first rule once again..

           The main essense is that , the first two parameters, if are equal to or less than 32 bits (like int), are pushed to the ECX and EDX Registers. 
           Rest are pushed to stack.

So it means if the first two parameters (in our case int and int) are equal to or less than 32 bits each (they are as int is 4 byte), then they are pushed to ECX and EDX registers. So basically the parameters are not pushed to the stack, but to the registers itself in this case, so nothing to clear!!!

So following this rule, do we expect to see ret 8, when the function is void fp (int a, int b, double c)? Yes you will see that.

So what would we see when the function is void fp(double a, int b)?
Ans: You would see ret 8, because out of the first two parameters, only second is less than or equal to 32 bits, so only that can be pushed to the register and first (8 bytes) is pushed to stack and hence ret 8.

__thiscall
=-=-=-=-=-

  • Default calling convention, for calling member functions in C++. But if the member function, contains dynamic argument list, then the default calling convention falls back to the dirty __cdecl (please don't fire me saying dirty :P)
  • The parameters are passed from right to left and more importantly the this pointer for objects is passed to the ECX (ofcourse for non-static methods)

Things I didnt tell you - > There is also __clrcall for clr  :P

I guess its enough for the day. I would leave you thinking about whatever you can, on this topic. Hope, I could clear some of the common doubts about calling conventions. Let me know if I left something here, i will give it a shot in part 2 under this topic. Don't foget to provide comments/feedback.

__cdecl bye_bye(see you soon with a new and exiting topic)

My Second Blog ever!!

Hello Guys,

"Putting pen on paper" for the second time ever (as far as blogging is concerned). I will be targetting mainly on the technical learnings that I have learnt and will try to pass it over through this great medium of technet.

As a beginner I have had many road blocks understanding topics (its not that I am still not having those :) ) . I will try to put in a way where each one can understand the point, be it a beginner (or users who have not even begun).

Keep pouring comments so that I am always pumped up to deliver more and more good quality blogs everytime.

Page view tracker