Mi pregunta, como el título mencionado, es obvia, y describo el escenario en detalle. Hay una clase llamada Singleton implementado por el patrón singleton de la siguiente manera, en singleton.h archivo:Múltiples instancias de singleton en bibliotecas compartidas en Linux
/*
* 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_ */
a continuación, hay un plugin llamado hello.cpp de la siguiente manera:
#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;
}
se puede ver que el complemento llame al singleton y cambie el atributo num en el singleton.
pasado, hay una función principal de utilizar el producto único y el plugin de la siguiente manera:
#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);
}
y el makefile es el siguiente:
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
es así, ¿cuál es la salida? pensé que es siguiente:
singleton.num in main : 100
singleton.num in hello.so : 100
singleton.num in hello.so after ++ : 101
singleton.num in main : 101
sin embargo, la salida real está siguiendo:
singleton.num in main : 100
singleton.num in hello.so : -1
singleton.num in hello.so after ++ : 0
singleton.num in main : 100
Esto demuestra que hay dos instancias de la clase singleton.
¿Por qué?
¿Desea que este singleton sea único para el único proceso que está ejecutando? ¿O un singleton "en todo el sistema" en violación de todo lo que la memoria protegida nos ofrece? – sarnold
La pregunta, a menos que se indique explícitamente, generalmente es cualquier cosa menos obvia. ¿Desea que las bibliotecas compartidas compartan el singleton o no?¿Teorizas acerca de cualquier comportamiento o realmente lo experimentas? No hay forma de saberlo a menos que nos lo diga. – 9000
@sarnold: hay un patrón bien conocido de singletons en todo el sistema que no están limitados por el espacio de direcciones: se llama servidor. Pero hasta que el cartel original diga el propósito de su código, es difícil decir si este patrón se ajusta. – 9000