Sunday, April 27, 2014

C++ 11 tuple


In C++ 11 standard library, tuple is introduced which can hold values of heterogeneous data type in one object. It is also known as extended pair. We can keep any number of values in tuple.

Let’s see following example to understand how to use tuple,

#include <tuple>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char* argv[])
{
     tuple<string,int,double,int> info("Pranit",27,25000,86);

     return 0;
}




To use tuple we first need to include tuple (#include <tuple>) header file in C++ code. We will be using cout and string so we also included <string> and <iostream> header files. 

In code, we have initialized tuple info to keep information regarding ‘name’:string, ‘age’:int, ‘salary’:double, ‘year’:int.

tuple<string,int,double,int> info("Pranit",27,25000,86);

Here we have defined and initialized tuple at same place, we can also use convenience function to initialize value after defining it like,

tuple<string,int,double,int> info; //defining tuple
info = make_tuple("Pranit",27,25000,86); //initializing tuple

To access values of tuple we can use get function,
get<0>(info); // accessing name of info
get<2>(info); // accessing salary of info
get<3>(info); // accessing name of year

If by mistake you give out of range value to get function, it will give compile time error.

get<5>(info); //error :: index from 0 to 3 is only permissible

get function returns reference to element, so we can change value of element by assigning value.
get<2>(info) = 20000; // change value of  salary from 250000 to 20000

We can extract all values of tuple using std::tie function, also, if we want to ignore any of the value we can use std::ignore.

tie(name,age,salary,year) = info; // extracted all values in corresponding variables
tie(name,std::ignore,salary,year) = info; // ignoring age value

Value of one tuple can be assigned to another tuple using assignment operator.

tuple<string,int,double,int> info1;
info1 = info;

Complete code,

#include <tuple>
#include <iostream>
#include <string>

using namespace std;

int main(int argc, char* argv[])
{
     tuple<string,int,double,int> info("Pranit",27,25000,86);//defining and initilizing
     //tuple<string,int,double,int> info; //defining tuple
     //info = make_tuple("Pranit",27,25000,86); //initilizing tuple
    
     get<0>(info); // accessing name of info
     get<2>(info); // accessing salary of info
     get<3>(info); // accessing name of year

     //get<5>(info); //error :: index from 0 to 3 is only permissible

     get<2>(info) = 20000; // change value of  salary from 250000 to 20000

     string name;
     int age;
     double salary;
     int year;

     tie(name,age,salary,year) = info; // extracted all values in corresponding variables
     tie(name,std::ignore,salary,year) = info; // ignoring age value, other values are extracted

     tuple<string,int,double,int> info1;
     info1 = info;

     return 0;
}



Saturday, April 26, 2014

Calling Conventions


Calling conventions is very important concept of C++ programming. Calling conventions decides two things, how arguments will be passed on stack and who will clear the stack.



In this article I will describe (and will prove it) two calling conventions, __cdecl and __stdcall.

In case of both __cdecl and __stdcall, arguments will be pushed on stack from right to left. Difference is, in __cdecl caller clears the stack, while in __stdcall callee will clear stack.

Let’s consider following code,

int __stdcall StdCall(int a,int b)
{
      return a + b;
}

int __cdecl Cdecl(int a,int b)
{
      return a + b;
}


int main(int argc, char* argv[])
{
      StdCall(10,20);
      Cdecl(10,20);
      return 0;
}


In this code, StdCall and Cdecl take two ints and returns there addition. I kept code simple to illustrate concept.
Now we will see code’s assembly equivalent to understand how calling conventions do the trick.  I am using Visual Studio to get assembly code. Here I am showing assembly code in parts.

Call to StdCall

push  20                            ; 00000014H
push  10                            ; 0000000aH
call  ?StdCall@@YGHHH@Z             ; StdCall

 Definition of StdCall

?StdCall@@YGHHH@Z PROC                                 ; StdCall, COMDAT
       push   ebp
       mov    ebp, esp
       sub    esp, 192                          ; 000000c0H
       push   ebx
       push   esi
       push   edi
       lea    edi, DWORD PTR [ebp-192]
       mov    ecx, 48                                  ; 00000030H
       mov    eax, -858993460                          ; ccccccccH
       rep stosd
       mov    eax, DWORD PTR _a$[ebp]
       add    eax, DWORD PTR _b$[ebp]
       pop    edi
       pop    esi
       pop    ebx
       mov    esp, ebp
       pop    ebp
       ret    8
?StdCall@@YGHHH@Z ENDP                                 ; StdCall
_TEXT  ENDS
END

In call to StdCall, it pushes arguments from right to left, i.e. 20, 10. And look at definition of StdCall, you can see ret 8. This is return statement, and don’t get confused with return statement of C++, here return statement doesn’t return value, but pass control from where this function getting called. ret 8 means it will return control by clearing stack with 8 bytes (adds 8 bytes to stack pointer, esp ). In 32 bit OS int are of 4 bytes, we are passing two ints so that will make it 8 bytes. So callee has cleaned the stack.

Now look at Cdecl calling convention.

Call to Cdecl

push  20                            ; 00000014H
push  10                            ; 0000000aH
call  ?Cdecl@@YAHHH@Z                     ; Cdecl
add   esp, 8

Definition of Cdecl

?Cdecl@@YAHHH@Z PROC                            ; Cdecl, COMDAT
      push  ebp
      mov   ebp, esp
      sub   esp, 192                      ; 000000c0H
      push  ebx
      push  esi
      push  edi
      lea   edi, DWORD PTR [ebp-192]
      mov   ecx, 48                             ; 00000030H
      mov   eax, -858993460                     ; ccccccccH
      rep stosd
      mov   eax, DWORD PTR _a$[ebp]
      add   eax, DWORD PTR _b$[ebp]
      pop   edi
      pop   esi
      pop   ebx
      mov   esp, ebp
      pop   ebp
      ret   0
?Cdecl@@YAHHH@Z ENDP                            ; Cdecl
_TEXT ENDS

Like StdCall, here in Cdecl both the arguments are pushed from right to left, and then call to function is made. However after call statement, you can see              add  esp, 8, which adds 8 to esp. esp points to top of stack. Adding 8 to means it is clearing 8 bytes (because stack grows from higher to lower memory). So here caller is clearing stack. Contrary to StdCall here you can see, ret 0, which just returns control and do not anything to stack pointer. So, in this case caller clears the stack.


Please add comments for your queries and suggestions. 

Thursday, April 3, 2014

Never throw exception from destructor


In C++, if you get exception in your code, you can handle it using try … catch block. If your code in try block throws exception, it will be caught in catch block.  

In catch block you can either gracefully close, or resume your application depending on severity of exception.

If you do not handle exception in try.. catch block, C++ runtime will call abort() function and application will crash.

So code which can throw exception should be wrapped in try .. catch block. So long so good.

Compiler is good at handling one exception at a time. If your code try to throw more than one exception at a time, application will definitely crash by calling abort() function. (I don’t know why)

And for the same reason, it is considered to be bad practice, to throw exception from destructor.

Let’s see some examples to understand concept.

Here, I am throwing exception from try and it will get caught in catch.  

int main(int argc, char* argv[])
{
     try
     {   
          throw "Exc";
     }
     catch(...)
     {
          std::cout<<"Exception caught"<<std::endl;
     }
     return 0;
}

Output: Exception caught

Now, consider following example, I am throwing exception from destructor. Destructor will get called in two cases, 1) You have created object on heap using new operator and, call delete to destroy object. 2) You have created object on stack, and object goes out of scope.  

class Sample
{
public:
     ~Sample()
     {
          throw "Exc";
     }
};

int main(int argc, char* argv[])
{
     try
     {   
          Sample s;
          throw "ExcMain";
          //other code
     }
     catch(...)
     {
          std::cout<<"Exception caught"<<std::endl;
     }
     return 0;
}

Output : Crash!!!

When “throw ExcMain”, throws exception, stack unwinding starts, and your object “s” goes out of scope,  which calls it’s destructor, which will again throw exception. 

So you have two exceptions at a time. And C++ runtime will call abort().

So never throw exception from destructor.

Please give your suggestion and feedback by leaving comment below article.


Thanks.