【发布时间】:2011-12-24 08:59:29
【问题描述】:
正如标题所提到的,我的问题很明显,我详细描述了这个场景。 在singleton.h文件中有一个由单例模式实现的名为singleton的类,如下所示:
/*
* singleton.h
*
* Created on: 2011-12-24
* Author: bourneli
*/
#ifndef SINGLETON_H_
#define SINGLETON_H_
class singleton
{
private:
singleton() {num = -1;}
static singleton* pInstance;
public:
static singleton& instance()
{
if (NULL == pInstance)
{
pInstance = new singleton();
}
return *pInstance;
}
public:
int num;
};
singleton* singleton::pInstance = NULL;
#endif /* SINGLETON_H_ */
然后,有一个名为 hello.cpp 的插件如下:
#include <iostream>
#include "singleton.h"
extern "C" void hello() {
std::cout << "singleton.num in hello.so : " << singleton::instance().num << std::endl;
++singleton::instance().num;
std::cout << "singleton.num in hello.so after ++ : " << singleton::instance().num << std::endl;
}
可以看到插件调用了singleton并改变了singleton中的属性num。
最后,使用单例和插件的主要功能如下:
#include <iostream>
#include <dlfcn.h>
#include "singleton.h"
int main() {
using std::cout;
using std::cerr;
using std::endl;
singleton::instance().num = 100; // call singleton
cout << "singleton.num in main : " << singleton::instance().num << endl;// call singleton
// open the library
void* handle = dlopen("./hello.so", RTLD_LAZY);
if (!handle) {
cerr << "Cannot open library: " << dlerror() << '\n';
return 1;
}
// load the symbol
typedef void (*hello_t)();
// reset errors
dlerror();
hello_t hello = (hello_t) dlsym(handle, "hello");
const char *dlsym_error = dlerror();
if (dlsym_error) {
cerr << "Cannot load symbol 'hello': " << dlerror() << '\n';
dlclose(handle);
return 1;
}
hello(); // call plugin function hello
cout << "singleton.num in main : " << singleton::instance().num << endl;// call singleton
dlclose(handle);
}
生成文件如下:
example1: main.cpp hello.so
$(CXX) $(CXXFLAGS) -o example1 main.cpp -ldl
hello.so: hello.cpp
$(CXX) $(CXXFLAGS) -shared -o hello.so hello.cpp
clean:
rm -f example1 hello.so
.PHONY: clean
那么,输出是什么? 我认为有以下几点:
singleton.num in main : 100
singleton.num in hello.so : 100
singleton.num in hello.so after ++ : 101
singleton.num in main : 101
但是,实际输出如下:
singleton.num in main : 100
singleton.num in hello.so : -1
singleton.num in hello.so after ++ : 0
singleton.num in main : 100
证明单例类有两个实例。
为什么?
【问题讨论】:
-
你想让这个单例成为你正在执行的一个进程的单例吗?还是违反所有受保护内存为我们提供的“系统范围”单例?
-
除非明确说明,否则问题通常并不明显。您是否希望共享库共享单例?您是否对任何一种行为进行理论化或实际体验?除非您告诉我们,否则无法知道。
-
@sarnold:有一种众所周知的系统范围的单例模式不受地址空间的限制:它被称为服务器。但在原发帖人说出他的代码的用途之前,很难判断这种模式是否适合。
-
@9000:哈哈!好点子。 :) 这里仍然没有类似服务器行为的证据,所以我认为不是这样。 :)