Where the hell am I?

Just in case you’re wondering where the hell am I and why I am not writing new stuff, I am on a short vacation. It’s holidays time here in Israel, so I took the liberty to split for a couple of weeks. I am actively sweeming in different sees, traveling around the country and sitting home doing nothing. Fiesta will be over on Oct. 22. Until then, have fun! :-)

New article – How inheritance, encapsulation and polymorphism work in C++

This concludes a month of work. Somehow I, again, ended up with huge article and explains lots of different things.

In this article, I am explaining how the three whales of OOP implemented in C++. How encapsulation works. How overloading of methods works. What is the structure of C++ object compared to C structure. How polymorphism works. What’s the structure of virtual methods table and how inheritance affects it. And many other things. Hope you will find it interesting. Read it here.

How inheritance, encapsulation and polymorphism work in C++

Table of contents

IntroductionBACK TO TOC

Inheritance, encapsulation and polymorphism are undoubtedly the cornerstones of OOP/OOD in general and C++ in particular.

When programming C, it is very easy to remember how things work. You know that when you add an int variable to a structure it mostly grows by four bytes. You know that long is either four or eight bytes long depending on the architecture you’re working with.

Things are less obvious when moving to C++. OOP brings more abstractions to the program. As a result you are no longer sure if a+b sums two numbers or calls some overloaded operator method that concatenates contents of two files together.

In this article, I would like to give you a short insight into what’s going on behind the scenes. In particular we’ll see how the three whales of OOP work in C++.

Things that I am going to show in this article may differ from compiler to compiler. I will talk mostly about g++ (version 4.2.3). Note however, that same ideas apply everywhere.

EncapsulationBACK TO TOC

As you know, encapsulation is a principle by which same entity, the object, encapsulates data and methods that manipulate the data. You may be surprised to find out that underneath, class methods are just plain functions.

How methods workBACK TO TOC

In C++ there’s one fundamental difference between plain functions and class methods. Class methods receive one additional argument and that is the pointer to the object whose data the method is expected to manipulate. I.e. first argument to a method is pointer to this.

To speed things up, C++ developers used single CPU register (ECX/RCX on x86/x86_64) to pass pointer to this, instead of passing it via stack as if it was a regular function argument (no longer true in x86_64).

Otherwise, objects know nothing about methods that operate on them.

How overloading worksBACK TO TOC

Another thing that we have to take care of in C++ is how to distinguish between some_function() and some_class::some_function(). Or between some_class::some_function( int ) and some_class::some_function() I.e. what’s the difference between two methods with the same name that receive different number and type of arguments? What is the difference between method and function that has same name?

Obviously, out of linker, compiler and preprocessor, linker is the one that should be aware of the above difference. This is because we may have some_function() in some distant object file. Linker is the component that should find this distant function and interconnect the call to the function and the actual function. Linker uses function name as a unique identifier of the function.

To make things work, g++ and any other modern compiler, mangles the name of the method/function and makes sure that:

  1. Mangled method name includes name of the class it belongs to (if it belongs to any class).
  2. Mangled method name includes number and type of arguments method receives.
  3. Mangled method name includes namespace it belongs to.

With these three, some_class::some_function() and some_function() will have totally different mangled name. See the following code sample.

namespace some_namespace
{
    class some_class
    {
    public:
        some_class() { }
        void some_method() { }
    };
};

class some_class
{
public:
    some_class() { }
    void some_method() { }
};

void some_method()
{
    int a;
}

g++ will turn:

  • void some_class::some_method() into _ZN10some_class11some_methodEv
  • void some_namespace::some_class::some_method() into _ZN14some_namespace10some_class11some_methodEv
  • void some_method() into _Z11some_methodv

Adding integer argument to void some_method() will turn it from _Z11some_methodv to _Z11some_methodi.

How mangling solves the problemBACK TO TOC

So when you create two methods with same name, but with different arguments, compiler turns them into two functions with different names. Later, when linker links the code together it doesn’t know that these are two methods of the same class. From linkers standpoint, these are two different functions.

Structure and size of the objectBACK TO TOC

You probably already know that C++ class and good old C structures are nearly the same thing. Perhaps the only difference is that all class members are private unless specified otherwise. On the contrary, all structure members are public.

When looking at the memory layout of the object, it is very similar to C structure.

Differences begin when you add virtual methods. Once you add virtual methods to the class, compiler will create virtual methods table for the class. Then it will place pointer to the table in the beginning of each instance of this class.

So, bear in mind that once your class has virtual methods, each object of this class will be four or eight bytes (depends on whether you have 64-bit support or not) bigger.

Actually, pointer to the virtual methods table does not have to be at the beginning of the object. It is just handy to keep it at the beginning, so g++ and most of the modern compilers do it this way.

Adding virtual methods to the class will also increase amount of RAM your program consumes and its size on your hard drive.

How inheritance and polymorphism workBACK TO TOC

Lets say we have two classes. A and B. Class B inherits from class A.

#include <iostream>

using namespace std;

class A
{
public:
    A() { a_member = 0; }
    int a_member;
};

class B : public A
{
public:
    B() : A() { b_member = 0; };
    int b_member;
};

int main()
{
    A *a = new B;
    a->a_member = 10;

    return 0;
}

The interesting thing to notice here is that a actually points to instance of class B. When dereferencing a_member, we’re actually dereferencing a_member that defined in class A, but belongs to class B (via inheritance). To make this happen, compiler has to make sure that common part of both classes (a_member in our case) located at the same offset in the object.

Now what if we have some virtual methods.

How basic polymorphism worksBACK TO TOC

Let’s change our example a bit and add some virtual methods.

#include <iostream>

using namespace std;

class A
{
public:
    A() { a_member = 0; }
    virtual int reset() { a_member = 0; }
    void set_a_member( int a ) { a_member = a; }
    int get_a_member() { return a_member; }
protected:
    int a_member;
};

class B : public A
{
public:
    B() : A() { b_member = 0; };
    virtual int reset() { a_member = b_member = 0; }
    virtual void some_virtual_method() { }
    void set_b_member(int b ) { b_member = b; }
    int get_b_member() { return b_member; }
protected:
    int b_member;
};

int main()
{
    B *b = new B;
    A *a = b;

    b->set_b_member( 20 );
    b->set_a_member( 10 );

    a->reset();

    cout << b->get_a_member() << " " << b->get_b_member() <<
        endl;

    return 0;
}

If you compile and run this program it will obviously print “0 0”. But how, you may ask. After all we did a->reset(). Without our understanding of polymorphism we could think that we’re calling method that belongs to class A.

The reason it works is because when compiler sees code that dereferences pointer to A it expects certain internal object structure and when it dereferences pointer to B it expects different object structure. Let us take a look at both of them.

However even more important here is the structure of the virtual methods tables of both classes.

It is because of the virtual methods table structure compilers knows what virtual method to call. When it generates the code that dereferences pointer to A, it expects that first method in the virtual methods table of the object will be pointer to right reset() routine. It doesn’t really care if the pointer actually points to B object. It will call first method of the virtual methods table anyway.

How multiple inheritance worksBACK TO TOC

Multiple inheritance makes things much more complicated. The problem is that when class C inherits from both A and B, we should have both members of class A and class B in the instance of class C.

#include <iostream>

using namespace std;

class A
{
public:
    A() { a_member = 0; }
protected:
    int a_member;
};

class B
{
public:
    B() { b_member = 0; }
protected:
    int b_member;
};

class C : public A, public B
{
public:
    C() : A(), B() { c_member = 0; }
protected:
    int c_member;
};

int main()
{
    C c;

    A *a1 = &c;
    B *b1 = &c;

    A *a2 = reinterpret_cast<A *>( &c );
    B *b2 = reinterpret_cast<B *>( &c );

    printf( "%p %p %p\n", &c, a1, b1 );
    printf( "%p %p %p\n", &c, a2, b2 );

    return 0;
}

Once we cast pointer to class C into class B, we cannot keep the value of the pointer as is because first fields in the object occupied by fields defined in class A (a_member). Therefore, when we do casting we have to do a very special kind of casting – the one that changes the actual value of the pointer.

If you compile and run above code snippet, you will see that all the values are the same except for b1, which should be 4 bytes bigger than other values.

This is what (C style casting in our case) casting does – it increments the value of the pointer to make sure that it points to the beginning of the, inherited from B, part of the object.

In case you wonder what other types of casting will do, here is a short description.

Difference between different casting typesBACK TO TOC

There are five types of casting in C++.

  1. reinterpret_cast<>()
  2. static_cast<>()
  3. dynamic_cast<>()
  4. const_cast<>()
  5. C style cast.

I guess you know already what const_cast<>() does. Also, it is only a compile time casting. C style cast is same as static_cast<>(). This leaves us with three types of casting.

  1. reinterpret_cast<>()
  2. static_cast<>()
  3. dynamic_cast<>()

From the above example we learn that reinterpret_cast<>() does nothing to the pointer value and leaves it as is.

static_cast<>() and dynamic_cast<>() both modify value of the pointer. The difference between two is that the later relies on RTTI to see if the casting is legal – it looks inside the object to see if it truly belongs to the type we’re trying to cast from. static_cast<>() on the other hand, simply increments the value of the pointer.

Polymorphism and multiple inheritanceBACK TO TOC

Things getting even more complicated when we have virtual methods in each one of the classes A, B and C that we already met. Let’s add following virtual methods to the classes.

virtual void set_a( int new_a ) { a_member = new_a; }

To class A.

virtual void set_b( int new_b ) { b_member = new_b; }

To class B and

virtual void set_c( int new_c ) { c_member = new_c; }

To class C.

You could have assumed that even in this case class C objects will have only one virtual tables methods, but this is not true. When you static_cast class C object into class B object, class B object must have its own virtual tables method. If we want to use same casting method as with regular objects (that is adding few bytes to the pointer to reach right portion of the object), then we have no choice but to place another virtual tables method in the middle of the object.

As a result, you can have many different virtual methods tables for the same class. The above diagram shows very simple case of inheritance and the truth is that it does not get more complicated than this. Take a look at the following, more complex, class hierarchy.

It may surprise you, but structure of the class X object will be quiet simple. In our previous example inheritance hierarchy had two branches. This one has three:

  1. A-C-F-X
  2. D-G-X
  3. B-E-H-X

All end up with X of course. They are a little longer than in our previous example, but there is nothing special about them. The structure of the object will be the following:

As a rule of thumb, g++ (and friends) calculates the branches that lead to the target class, class X in our case. Next it creates a virtual methods table for each branch and places all virtual methods from all classes in the branch into virtual methods table. This includes pointer to virtual methods of the class itself.

If we project this rule onto our last example. A-C-F-X branch virtual methods table will include pointers to virtual methods from classes A, C, F and X. Same with other two branches.

What if we try something even more complicatedBACK TO TOC

The thing is that you can’t. Lets say we try to create even more complicated hierarchy by changing class D from our previous example to inherit from class C.

This will immediately create ambiguous inheritance and the compiler will not hesitate to tell you that this is what happened. This is because now class X will have all members of classes A and C twice. Once it will have it via A-C-F-X branch and once via A-C-D-G-X branch. It will not tell you that there’s a problem immediately. Instead, once you will try to reference one of the members of X inherited from either A or C, g++ will tell you that it has two variations of the same member/method and that it does not know which one of them to call.

This what would be g++ output if you try to compile this file.

main.cc: In function 'int main()':
main.cc:110: error: request for member 'set_a' is ambiguous
main.cc:29: error: candidates are: virtual void A::set_a(int)
main.cc:29: error:                 virtual void A::set_a(int)

All this because I was trying to do x.set_a( 20 ); in line 110.

Few words about C++ constructorsBACK TO TOC

I guess you know what constructors are good for. In light of what we’ve seen, you may ask yourself, who is building all those virtual methods tables and who writes right pointer into the object.

Obviously compiler builds all the virtual methods tables. And constructor is the one who fills in the right virtual methods table. And this is another reason why you cannot call constructor directly – you don’t want to mess up with virtual methods tables.

ConclusionBACK TO TOC

For now, I think we had some very nice insight of what’s going on inside of the objects you create. Hope you find it useful. In case you have something to say, please leave comments here or send me emails to alex@alexonlinux.com.

Todo list

I usually have something like 10 different articles, on different subjects in stock. Every day I pick myself an article or a couple and add few paragraphs.

Because this is how I work, I often don’t release new stuff for months and then release several huge articles in just one week.

This way of working may make you think that I am not writing new stuff. To devaporate any misunderstandings on the subject, I decided to add a todo list. You can find it on the rightmost pane just below quick links.

In the list I have names of the articles I am working on. Some articles may be missing from there. It is either because I want to make them a surprise or because I am not sure if I will ever release them. But otherwise it’s all there.

I also think to add some sort of counter that would tell how many words I’ve written today and perhaps in a week period. I’ll need a plugin for that.

Marketing experiment

Marketing is the driving force behind many things. This includes web-sites of course.

Few weeks ago I decided that creating good content for the web-site is not enough. It is important to promote it as well. So I thought if I put so much time into writing stuff, why not spend couple of minutes making sure people actually read the stuff I write.

I found a guy writing about guitars. He opened a new blog and claimed that he will try to reach an average of 5000 visitors a day by the end of six month period. Unfortunately it seems that he has failed. Yet I think he will be pleased to know that he has inspired me to try something similar as well.

No, I will not reach 5000 visitors a day. But I will at least try to bring visitors not only by writing the content, but by promoting it as well.

After reading his blog couple of weeks ago I went down and did something I never did before. I posted my most popular article on the most popular social bookmarking services. Guess what. Nearly 1500 visitors has visited within 24 hours after that.

Today, few weeks after, I have something like 40 daily visitors more than I had before bookmarking my article. All because I spent 5 minutes registering at digg.com and delicious.com. So I think the experiment was a success :D

Wow! My tcpdump for Dummies is on the front page of delicious.com

[singlepic=756,512,384,,center]

Copyright infringement tale continued

This post concludes this story – some gentleman decided that he can make money by publishing my content.

Yesterday, something like a couple of weeks since I filed DMCA complaint against this guy, I received an email from blogspot’s tech support stating that all posts infringing my copyrights are gone.

I want to thank blogspot for taking care about this.

New article – 32bit vs 64bit computers, the QA

This article describes the difference between the two. Does getting 64-bit support really worth the time and the effort and perhaps the the money? Find out here.

32bit vs 64bit computers, the QA

Table of contents

IntroductionBACK TO TOC

Many wonder what is the real difference between 64-bit and 32-bit computers. Is paying a little extra for 64-bit support really worth it?

What 64-bit support mean?BACK TO TOC

This can mean many things actually. This article dedicated to recent (relatively of course) addition of the 64-bit support in AMD’s and Intel’s micro-processors. Processors supporting 64-bit calculations exists for many years. However these were industry class processors, very expensive and powerful. Couple of year ago, first AMD and then Intel began selling 64-bit processors designed with home user in mind. This historical change is the one I would like to review in this article.

What the difference between the 32-bit and 64-bit anyway?BACK TO TOC

Processors with 64-bit support are those that natively support operations with 64-bit long numbers – you need lots of bits to accommodate large numbers. You may be a little confused by the fact that built into both Linux and Windows calculators easily sum a pair of nearly every possible numbers, including a pair of very big numbers. The thing is that 32-bit CPUs only simulate calculations with large numbers.

In 32-bit computer, summing two 64-bit numbers takes 10 and even more times than summing two 32-bit numbers. On the other hand, in 64-bit computers summing two 64-bit numbers takes same period of time as summing two 32-bit numbers.

General purpose registersBACK TO TOC

Another, less obvious, difference between the two is that processors with 64-bit support has additional 8 general purpose registers – these are small pieces of memory that are built into processor itself and help it to do its job. Importance of the later addition often overlooked, however this is the change that has brought a truly significant performance boost to 64-bit processors over their 32-bit predecessors.

What additional registers good for?BACK TO TOC

Actually the CPU does most of its operations using registers. Registers work as fast as the CPU itself, while RAM is much slower. So in terms of performance, it is better to do as many calculations using registers as possible. The problem is however that having registers is very expensive.

Intel’s Itanim processors have 128 general purpose registers. Itaniums are an industry class processors and are very expensive.

Additional 8 registers is a significant addition that let the CPU to speed up some of its operations by a large margin.

So how good 64-bit really is?BACK TO TOC

With 64-bit extension you get 10% performance boost for free. This number can be different from system to system of course, but I think we can presume this is pretty much the average.

What about OS and software?BACK TO TOC

When you have some neat feature in your CPU, you need software uses it. This is why there are 32-bit operating systems and 64-bit operating systems. First knows nothing about 64-bit calculations and additional registers, while the later uses both of them all the time.

Same with regular software.

Does that mean that paying extra money for 64-bit Windows XP/Vista worth it?BACK TO TOC

It’s a bit complex. You cannot run 64-bit software on 32-bit operating system. So if you plan running anything that uses 64-bit, you will need 64-bit operating system.

Still for most of the users the answer would be negative. The problem is that most of the software for Windows is 32-bit. 64-bit versions are rarely available. You can run 32-bit software on 64-bit computer and 64-bit operating system, but buying 64-bit operating system is often useless because you may end up using 32-bit software all the time.

update: As Mr. rasmasyean kindly noted in the comments below, amount of physical RAM that you plan to have in your computer is another consideration that should be taken. 32-bit versions of both Windows XP and Windows Vista limit amount of supported physical RAM to 4GB. In case you need more RAM, you will need 64-bit version of Windows.

How about Linux?BACK TO TOC

Linux is completely different story. For most of the software there is a 64-bit version. Even if there is none, you can try to compile it yourself – it is not that complicated. And there is no difference between 64-bit and 32-bit operating system in terms of price. So go ahead, grab yourself a 64-bit Linux and enjoy its improved performance :D

New page – Interactive Disassembler (IDA) Macros

Few years ago I’ve written a script for IDA – Interactive Disassembler. IDA is a great tool I’ve been using for many years to analyze executable files. You can find more information about it here.

The script fixes how IDA analyzes executables produces with cygwin gcc. IDA does not show all symbol names properly. The script fixes this.

Finally, I decided that the script deserves a page of it’s own. Perhaps I will add more scripts to this page in the future, but for now it is the only habitant of this page.

Anyway, hope you will find it useful. The page is right here.