Mehrere Instanzen von Singleton über gemeinsam genutzte Bibliotheken unter Linux

Meine Frage, wie der Titel erwähnt, ist offensichtlich, und ich beschreibe das Szenario, in details.
Es gibt eine Klasse namens singleton implementierte singleton-pattern wie folgt in der Datei singleton.h:

/*
 * 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_ */

dann, es gibt ein plugin namens hello.cpp wie folgt:

#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;
}

können Sie sehen, dass der plugin-Aufruf des singleton, und ändern Sie das Attribut num in singleton.

letzten, es gibt eine main-Funktion verwenden Sie das singleton-und das plugin wie folgt:

#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);
}

und das makefile ist folgende:

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

also, was ist die Ausgabe?
Ich dachte, es ist folgende:

singleton.num in main : 100
singleton.num in hello.so : 100
singleton.num in hello.so after ++ : 101
singleton.num in main : 101

jedoch die tatsächliche Ausgabe ist folgende:

singleton.num in main : 100
singleton.num in hello.so : -1
singleton.num in hello.so after ++ : 0
singleton.num in main : 100

Beweist es, dass es zwei Instanzen der singleton-Klasse.

Warum?

Kommentar zu dem Problem
Möchten Sie dieses singleton ein singleton für den einen Prozess, die Sie ausführen? Oder ein "system-wide" singleton Verstoß gegen alle, die den geschützten Speicher bietet Sie uns? Kommentarautor: sarnold
Frage, sofern nicht explizit angegeben, ist in der Regel nichts, aber offensichtlich. Wollen Sie gemeinsame Bibliotheken teilen, singleton oder nicht? Sie theoretisieren über entweder Verhalten oder eigentlich erleben? Keine Möglichkeit zu wissen, es sei denn, Sie sagen uns. Kommentarautor: 9000
@sarnold: es ist eine gut bekannte Muster der system-weiten singletons, die sind nicht begrenzt durch Adressraum: es heißt, einen server. Aber bis das ursprüngliche Plakat erzählt die Zweck seinen code, es ist schwer zu sagen, ob dieses Muster passt. Kommentarautor: 9000
@9000: haha! guter Punkt. 🙂 Es gibt immer noch keine Hinweise auf server-wie Verhalten hier, so glaube ich nicht, dass es das ist. 🙂 Kommentarautor: sarnold

InformationsquelleAutor der Frage bourneli | 2011-12-24

Schreibe einen Kommentar