Sunday, April 14, 2013

Declaration,definition, Initialization

Declaration tells compilers about the name and type of something but omits certain details.

E.g.

extern int x;                    //object declaration
class ABC;                    // Class declaration
template<typename T> struct XYZ;   //template declaration


Declarations introduce new names into a program. Topics covered in this section include the following uses for declarations.


A definition provides compilers with the details the declaration omits. It is different for different types as follows:

1) For an object, the definition is where the compiler set aside the memory for the object.
2) For a function or function template, the definition provides the code body.
3) For a class or class template, the definition lists the member of the class  or templates.

e.g.

int x;                       // object definition
class ABC {           // class definition

private:
     int i;

}

template <typename T> struct XYZ {     // template definition

int i;

}

Initialization is the method of giving an object its first value. For objects generated from structs and classes, initialization is performed by constructors. Copy constructor is used to initialize an object with a different object of the same type.


References:

1) http://msdn.microsoft.com/en-us/library/sc8yf29y.aspx
2) Scott Meyers Effective C++ Chapter 0



Restricting the Copy constructor and assignment operator for a class object

Declare the copy constructor and copy assignment operator as private. By declaring a member function explicitly, you prevent compilers from generating their own version, and by making the functions private, you keep people from calling it.

Now the question comes, if we should declare them as protected or private. The advantage we get from declaring them private is that the error is generated at the compilation time and in case of the protected type access, it will be a linker time error.

So as Gopal says, earlier the better [:)]

Example follows:


class Base1 {

public:

        Base1():m_i(0) {}

private:
        Base1(const Base1&);
       Base1& operator=(const Base1&);

private:
        int m_i;
};

class Derived1 : public Base1 {

public:

Derived1():Base1(){}
Derived1(const Derived1& rhs):Base1(rhs) {}
Derived1& operator=(const Derived1& rhs){
   Base1::operator=(rhs);
}
};

int main ( void ) {

Base1 b1;
Derived1 d2;
Derived1 d1(d2);   // Compilation error here as base class copy constructor is private
return 0;
}

This will have compiler error.


If you declare the copy functions as protected, the linker error will be generated as follows:


/tmp/ccawBuy5.o: In function `Derived1::Derived1(Derived1 const&)':
test3.cpp:(.gnu.linkonce.t._ZN8Derived1C1ERKS_+0x14): undefined reference to `Base1::Base1(Base1 const&)'
collect2: ld returned 1 exit status







Access Specifiers Inheritance Behavior

BASE CLASS
Member
Inheritance Type
Public
Private
protected
Public
Public
Private
Protected
Private
 Not possible
Not possible
Not possible
Protected
Protected
Private
Protected

Default Constructors

Default constructors are constructors that doesn't accept any arguments. User can provide the default constructor, if user doesn't provide the default constructor compiler can automatically generate one based on the program needs if the class doesn't contain any const and reference members

Below are the conditions in which compiler will generate default constructor

1) If the class has member objects that has default constructor
2) If the base class of the class has default constructor
3) If the class has any virtual functions
4) If the class is derived from virtual base class


Note:

If you explicitly provide a constructor to the class then compiler wont generate default constructor and destructor. Its the programmers responsibility to provide all the necessary constructors and destructors.

This is applicable to the copy constructors as well.

For e.g. :


class Base1 {

public:

Base1(const Base1&);
Base1& operator=(const Base1&);

private:
        int m_i;

};

int main () {

Base1 b;

}

This will throw compiler error:


test3.cpp:19: error: base `Base1' with only non-default constructor in class without a constructor
test3.cpp: In function `int main()':
test3.cpp:38: error: no matching function for call to `Base1::Base1()'
test3.cpp:10: note: candidates are: Base1::Base1(const Base1&)








References:

1) http://www.informit.com/guides/content.aspx?g=cplusplus&seqNum=363
2) Effective C++ by Scott Meyers

Friday, April 12, 2013

Initialization and Uninitialization functions in shared library

When writing a shared library, it is sometimes useful to have a set of functions that get called when the library is loaded and unloaded.

Windows:

In Windows, this is done by implementing the DllMain function. This function is called by the loader whenever a DLL is loaded or unloaded into the address space of a process (and also when the process creates a new thread). A value is passed in as an argument to the DllMain function that indicates which event is occurring: DLL load or unload.


 BOOL WINAPI DllMain(HINSTANCE hinstDLL,  // DLL module handle
    DWORD fdwReason,              // reason called
    LPVOID lpvReserved)           // reserved
{
    hinstDLL  = NULL ;
    lpvReserved  = NULL ;

    switch (fdwReason)
    {
        case DLL_PROCESS_ATTACH:
               break;
        case DLL_THREAD_ATTACH:
               break;
        case DLL_THREAD_DETACH:
              break ;
        case DLL_PROCESS_DETACH:
            break;
     }
    return TRUE;
}

Linux:

On Linux, one must use the GCC __attribute__((constructor)) and __attribute__((destructor)) keywords to explicitly declare functions to be called on load and unload. These keywords cause the compiler/linker to add the specified functions to the __CTOR_LIST__ and __DTOR_LIST__ (“ConstrucTOR LIST” and “DestrucTOR LIST” respectively) in the object file. Functions on the __CTOR_LIST__ are called by the loader when the library is loaded (either implicitly or by dlopen()). The main purpose for this list is to call the constructors on global objects in the library. Conversely, functions on the __DTOR_LIST__ are called when the library is unloaded (either implicitly or by dlclose()). By adding initialization and clean-up functions to this list, one can effectively replicate the DllMain functionality on Linux.

void __attribute__ ((constructor)) my_load(void);
void __attribute__ ((destructor)) my_unload(void);

// Called when the library is loaded and before dlopen() returns
void my_load(void)
{
    // Add initialization code…
}
// Called when the library is unloaded and before dlclose() returns
void my_unload(void)
{
    // Add clean-up code…
}

 
References:
  1. http://msdn.microsoft.com/en-us/library/windows/desktop/ms682583%28v=vs.85%29.aspx 

Friday, April 5, 2013

stack overflow

Stack overflow could cause the program to terminate by sending SIGABRT signal.  You can detect this with latest gcc compiler(4.2 above) under gdb debugger.

Run the program under gdb and once the program terminates, check call stack(run bt command in gdb) and see your call stack for a call to the function __stack_chk_fail().

The interface __stack_chk_fail() will abort the function that called it with a message that a stack overflow has been detected. The program that called the function shall then exit.

Below is the output you will get when run xxxxxx program under gdb.

 /Developer/usr/bin/gdb  xxxxxx

(gdb) run

Program received signal SIGABRT, Aborted.
0x92fb9a6a in __pthread_kill ()

(gdb) bt
#0  0x92fb9a6a in __pthread_kill ()
#1  0x91d60acf in pthread_kill ()
#2  0x91d975ff in __abort ()
#3  0x91d98582 in __stack_chk_fail ()
#4  0x0019f2fc in CLocalSector::CreateSPIBuffer ()
#5  0x001a042c in CLocalSector::ReadStatus ()
#6  0x001966ee in CDM::readJobStatus ()
#7  0x00004402 in RunJobs ()
#8  0x0000c7c0 in main ()


References:

1) http://refspecs.linux-foundation.org/LSB_4.0.0/LSB-Core-generic/LSB-Core-generic/libc---stack-chk-fail-1.html

2) http://wiki.osdev.org/GCC_Stack_Smashing_Protector