Saturday, January 31, 2009

extern pitfalls in G++

Look at the example:
unit1.cpp

#include <iostream>
using namespace std;

int I = 2;
extern const int J = 10;
void FuncI();
void FuncJ();


int main()
{
cout << hex;
cout << "I, before " << I << " " << *(&I + 1) << endl;
FuncI();
cout << "I, after " << I << " " << *(&I + 1) << endl;
FuncJ();
}


unit2.cpp

extern long long I;
extern int J;


void FuncI()
{
I = I << 36;//causes contiguous memory damage
}


void FuncJ()
{
J++;//causes segmentation fault
}


The program compiles fine and the results are:

I, before 2 0
I, after 0 20
Segmentation fault


Why g++ compiler is so spoiled here. I don't know. In Visual Studio it's impossible to do such nasty things.

Sunday, January 25, 2009

Singleton pattern C++. My recipe.

Look into example

#include <iostream>
#include "SingletonPattern.h"


class A : public ISingleton<A>
{
//a few extra movements (friend declarations) is needed to create own non-public default ctor and dtor.
A() { j = 10;};
~A() {std::cout << "~A" << std::endl;};
friend class ISingleton<A>;
friend class std::auto_ptr<A>;

public:
//do not define any public ctors and dtor.
//do not define copy ctor and assign operator at all.

static int j;
void Test(int i) { std::cout << "A::Test(" << i << ") " << ++j << std::endl;};
};
int A::j = 10;


class B : public ISingleton<B>
{
public:
void Test(int i) { static int j = 0; std::cout << "B::Test(" << i << ") " << ++j << std::endl;};
};


class C : public ISingleton<C>
{
public:
virtual void Test(int i) { static int j = 0; std::cout << "C::Test(" << i << ") " << ++j << std::endl;};
};


class D : public C
{
public:
void Test(int i) { static int j = 0; std::cout << "D::Test(" << i << ") " << ++j << std::endl;};
};


int main()
{
A::GetSingleton().Test(5);
A& a = A::GetSingleton();
a.Test(6);
// A anotherA = A::GetSingleton();//compilation error, ok
// a = a;//compilation error, ok

B::GetSingleton().Test(3);
B& b = B::GetSingleton();
b.Test(100);
C::GetSingleton().Test(33);
D::GetSingleton().Test(23);//it doesn't work for D because ISingleton was defined for parent class C
b.Test(15);
}


A::Test(5) 11
A::Test(6) 12
B::Test(3) 1
B::Test(100) 2
C::Test(33) 1
C::Test(23) 2
B::Test(15) 3
~A



There are 3 singleton classes (A, B, C). As you see it's very simple to create singleton class, only inherit public ISingleton<ThisClass>.
A few cautions however are written on lines 7, 14, 15. First belongs to own default ctor and dtor. Well, usually singleton class encapsulates heap objects, so own destructor is needed. Own default constructor maybe also useful, but if initialization with arguments is needed, custom Init method is the case because ctors with arguments are unavailable with this singleton implementation.

Ok, look at the implementation code.

#ifndef _SINGLETON_PATTERN_INTERFACES_SVOLKOV_
#define _SINGLETON_PATTERN_INTERFACES_SVOLKOV_


#include <memory>


template <class T>
class ISingleton
{
protected:
ISingleton();
~ISingleton();
private:
ISingleton(const ISingleton&);
ISingleton& operator= (const ISingleton&);
static std::auto_ptr<T> _ptr;
friend class std::auto_ptr<T>;
public:
///Get singleton instance.
static T& GetSingleton();
};


template <class T>
std::auto_ptr<T> ISingleton<T>::_ptr;


template <class T>
ISingleton<T>::ISingleton()
{
}


template <class T>
ISingleton<T>::~ISingleton()
{
}


template <class T>
T& ISingleton<T>::GetSingleton()
{
if (!_ptr.get())
_ptr = std::auto_ptr<T>(new T());
return *(_ptr.get());
}


#endif

Lazy initialization is used to postpone instantiation process. Standard smart pointer is used to destroy object automatically when program is closing. This instantiation/deletion model is exactly what is usually needed for a singleton manager etc.
Please note that it's single-threaded pattern implementation, not multi-threaded.

Saturday, January 24, 2009

SIGSEGV on statement with std::string variable, G++.

If you have error report like

Program received signal SIGSEGV, Segmentation fault.
0xb7d2be69 in __gnu_cxx::__exchange_and_add () from /usr/lib/libstdc++.so.6
(gdb) where
#0 0xb7d2be69 in __gnu_cxx::__exchange_and_add () from /usr/lib/libstdc++.so.6
#1 0xb7d0dfcc in std::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string () from /usr/lib/libstdc++.so.6
...

or

Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0xb746b6d0 (LWP 9469)]
0xb7c5ce69 in __gnu_cxx::__exchange_and_add () from /usr/lib/libstdc++.so.6
(gdb) where
#0 0xb7c5ce69 in __gnu_cxx::__exchange_and_add () from /usr/lib/libstdc++.so.6
#1 0xb7c3e8e4 in std::string::assign () from /usr/lib/libstdc++.so.6
#2 0xb7c3e944 in std::string::operator= () from /usr/lib/libstdc++.so.6
...

or something similar,
check that memory under string variable isn't corrupted.
In my case the problem was with zeroed memory. In Visual Studio I used the ugly but effective construction like

string a;
memset(&a, 0, sizeof(a));

and I didn't have problems with it. But in g++ and in general I must be more accurate.

Friday, January 23, 2009

Method pointer G++

Look at this code:

#include <iostream>
using namespace std;


class A
{
public:
void Test(int i)
{
mc(&A::ma, i);
mc(mb, i);
};
protected:
void ma(int i) { cout << "A::ma(" << i << ") has been called" << endl;};
void mb(int i) { cout << "A::mb(" << i << ") has been called" << endl;};
void mc(void (A::*m)(int), int i) { cout << "A::mc "; (this->*m)(i);};
};


int main()
{
A a;
a.Test(5);
}


In Visual Studio it compiles fine. But in g++ the error occurs:
 
FPointer.cpp: In member function ‘void A::Test(int)’:
FPointer.cpp:11: error: no matching function for call to ‘A::mc(<unresolved overloaded function type>, int&)’
FPointer.cpp:16: note: candidates are: void A::mc(void (A::*)(int), int)


That's because g++ compiler expects strict writing. Compare lines 10 and 11 to solve this error.

Delegation pattern in C++. My recipe.

Look into example code:

#include "DelegationPattern.h"
#include <iostream>
using namespace std;


class Notifier : public INotifier
{
public:
void NotifyAll(int j)
{
std::vector<IDelegate*>::iterator i = _delegates.begin(), iEnd = _delegates.end();
for (; i != iEnd; i++)
{
(*i)->Invoke(j++);
}
}
};


class A : ISubscriber<A>
{
public:
void SubscribeAll(INotifier* notifier) { Subscribe(notifier, &A::ma); Subscribe(notifier, &A::mb);};
void UnsubscribeAll(INotifier* notifier) { Unsubscribe(notifier, &A::ma); Unsubscribe(notifier, &A::mb);};
void UnsubscribeSecond(INotifier* notifier) { Unsubscribe(notifier, &A::mb);};
void SubscribeFirst(INotifier* notifier) { Subscribe(notifier, &A::ma);};
protected:
void ma(int i) { cout << "A::ma(" << i << ") has been called" << endl;};
void mb(int i) { cout << "A::mb(" << i << ") has been called" << endl;};
};

class B : ISubscriber<B>
{
int _id;
public:
B(int id) : _id(id) {};
void SubscribeAll(INotifier* notifier) { Subscribe(notifier, &B::ma);};
void UnsubscribeAll(INotifier* notifier) { Unsubscribe(notifier, &B::ma);};
void ma(int i) { cout << "B(" << _id << ")::ma(" << i << ") has been called" << endl;};
};


int main()
{
Notifier notifier;
A a;

{
B b1(1);
B b2(2);

a.SubscribeAll(¬ifier);
notifier.NotifyAll(3);
b1.SubscribeAll(¬ifier);
notifier.NotifyAll(10);
a.SubscribeFirst(¬ifier);
a.UnsubscribeSecond(¬ifier);
a.UnsubscribeSecond(¬ifier);
b2.SubscribeAll(¬ifier);
notifier.NotifyAll(21);
}
notifier.NotifyAll(30);
}



Notifier is events source. It must be single instance and process all events.
Suppose you have 2 independent classes A and B, which want to receive some events from notifier. To achieve this goal they inherit ISubscriber interface and define inside themselves simple subscribe/unsubscribe methods. That's all. Program results are:

A::ma(3) has been called
A::mb(4) has been called
A::ma(10) has been called
A::mb(11) has been called
B(1)::ma(12) has been called
A::ma(21) has been called
B(1)::ma(22) has been called
B(2)::ma(23) has been called
A::ma(30) has been called


Here is the code that covers presented interfaces (DelegationPattern.h):

#ifndef _DELEGATION_PATTERN_INTERFACES_SVOLKOV_
#define _DELEGATION_PATTERN_INTERFACES_SVOLKOV_


#include <vector>
#include <algorithm>
class IDelegate;


///Simple notifier interface.
class INotifier
{
public:
void Subscribe(IDelegate* delegate) { _delegates.push_back(delegate);};
void Unsubscribe(IDelegate* delegate) { _delegates.erase(std::find(_delegates.begin(), _delegates.end(), delegate));};

protected:
std::vector<IDelegate*> _delegates;
};


/** Subscriber interface.
@remarks
Any class can become subscriber to register own methods as callbacks.
*/
template <class T>
class ISubscriber
{
public:
///Destructor.
virtual ~ISubscriber() = 0;
///Accepted arguments list for target callback method.
typedef void (T::*CallbackMethod) (int);

/** Register new delegate.
@remarks Actually any other arguments can be added here to distinguish event type to subscribe etc.
*/
void Subscribe(INotifier* notifier, typename ISubscriber<T>::CallbackMethod method);
/** Unregister delegate.
*/
void Unsubscribe(INotifier* notifier, typename ISubscriber<T>::CallbackMethod method);

protected:
std::vector<std::pair<INotifier*, IDelegate*> > _delegates;
};


/** Delegate object interface.
*/
class IDelegate
{
public:
///Call.
virtual void Invoke(int) = 0;
};


/** Delegate object with callback method pointer.
*/
template <class T>
class MethodDelegate : public IDelegate
{
template <typename U> friend class ISubscriber;
protected:
T* _object;
typename ISubscriber<T>::CallbackMethod _method;
public:
///Constructor.
MethodDelegate(T* object, typename ISubscriber<T>::CallbackMethod method)
: _object(object), _method(method) {};
///Call.
void Invoke(int);
};


template<class T>
void MethodDelegate<T>::Invoke(int i)
{
(_object->*_method)(i);
}


template <class T>
ISubscriber<T>::~ISubscriber<T>()
{
std::vector<std::pair<INotifier*, IDelegate*> >::iterator i = _delegates.begin(), iEnd = _delegates.end();
for (; i != iEnd; i++)
{
i->first->Unsubscribe(i->second);
delete(i->second);
}
}


template <class T>
void ISubscriber<T>::Subscribe(INotifier* notifier, typename ISubscriber<T>::CallbackMethod method)
{
std::vector<std::pair<INotifier*, IDelegate*> >::iterator i = _delegates.begin(), iEnd = _delegates.end();
for (; i != iEnd; i++)
{
if (i->first == notifier && ((MethodDelegate<T>*)i->second)->_method == method)
return;//already subscribed
}
IDelegate* delegate = new MethodDelegate<T>((T*)this, method);
_delegates.push_back(std::make_pair(notifier, delegate));
notifier->Subscribe(delegate);
}


template <class T>
void ISubscriber<T>::Unsubscribe(INotifier* notifier, typename ISubscriber<T>::CallbackMethod method)
{
std::vector<std::pair<INotifier*, IDelegate*> >::iterator i = _delegates.begin(), iEnd = _delegates.end();
for (; i != iEnd; i++)
{
if (i->first == notifier && ((MethodDelegate<T>*)i->second)->_method == method)
{
i->first->Unsubscribe(i->second);
delete i->second;
_delegates.erase(i);
return;
}
}
}


#endif



Make attention that it's only possible to define callback method with fixed arguments here (void method(int)), however it must be enough. In my program I used one (void method(object*)). 
Also note that it's single-threaded solution. I'm going to post multi-threaded version later.

Intro

Hi all.
My name is Sergey and i'm programmer from Samara, Russia. This is my first stuff in English (second at all) and I hope it will be some kind useful for me and readers.
What I'm planning here. First, to cover C++ programming language and all around. C++ is great, I really admire its. Second, C#, .NET framework, BizTalk server, etc Microsoft stuff. Maybe I'll mention about a non-recurring question or modern undertow here.
Let's Go.