Saturday, June 30, 2012

got multiple singleton instances

We meet a subtle bug while adopting singleton design pattern in a project. The singleton class creates multiple instances.
The image below depicts the dependency relationship between different modules.



The executable depends on two dynamic libraries, dynamic_lib1 and dynamic_lib2. And both dynamic_lib1 and dynamic_lib2 depends on static_lib. There is a singleton class in static_lib. dynamic_lib1 and dynamic_lib2 use get_instance method to retrieve the instance of the singleton class.
The basic skeleton of the singleton class is shown below:

 1 // singleton.h
 2 #pragma once
 3 
 4 class __declspec(dllexport)  singleton
 5 {
 6 public:
 7     singleton(void);
 8     ~singleton(void);
 9 
10     static singleton* instance;
11     static singleton* get_instance();
12 };
13 
14
15
// singleton.cpp
16 #include "singleton.h"
17 #include <iostream>
18 
19 singleton* singleton::instance;
20 
21 singleton::singleton(void)
22 {
23 }
24 
25 singleton::~singleton(void)
26 {
27 }
28 
29 
30 singleton* singleton::get_instance()
31 {
32     // lock here
33     if(!instance)
34     {
35         instance = new singleton();
36     }
37     // unlock here
38     return instance;
39 }


But when we run the executable, we're surprised to find that the the use of get_instance method in dynamic_lib1 and dynamic_lib2 doesn't share the same instance.

After thinking about it carefully, it's clear that the bug is caused by we use static_lib3 as a static library. When we compile dynamic_lib1 and dynamic_lib2, they both link with static_lib, and each get a separate copy of the singleton::instance in data section.

But be aware that the behavior is compiler specific. The singleton is still singleton when I tested with gcc. And the singleton got created multiple instances when I tested microsoft's C++ compiler and apple's developer tools.