dlclose () funktioniert nicht mit Factory-Funktion und komplexer statischer Funktion?

Ich erstelle ein einfaches Plug-in-Framework, in dem ich eine gemeinsam genutzte Bibliothek (d. H. Ein Plug-in) öffnen (), die bereitgestellten Factory-Funktionen überprüfen und verwenden und schließlich dlclose (), ohne Spuren zu hinterlassen.

Mein Fabriksystem ist trivial, mit einer einzigen exportierten Funktion, die einen Zeiger auf eine gemeinsame Basisklasse zurückgibt. Um zu überprüfen, ob das Plugin korrekt entladen wurde, habe ich ein statisches Objekt, dessen Destruktor einen Bool aus dem Hauptprogramm setzt.

Hier ist das Hauptprogramm:

// dltest.cpp follows. Compile with g++ -std=c++0x dltest.cpp -o dltest -ldl
#include <dlfcn.h>
#include <iostream>
using namespace std;
int main(int argc, char** argv)
{
    if (argc > 1)
    {
        void* h = dlopen(argv[1], RTLD_NOW|RTLD_LOCAL);
        if (!h)
        {
            cerr << "ERROR: " << dlerror() << endl;
            return 1;
        }
        bool isFinilized = false;
        *(bool**)dlsym(h, "g_finilized") = &isFinilized;
        cout << boolalpha << isFinilized << endl;
        if (dlclose(h))
        {
            cerr << "ERROR: " << dlerror() << endl;
            return 2;
        }
        cout << boolalpha << isFinilized << endl;
    }
    return 0;
}

Und der Code des Plugins ist:

// libempty.cpp follows. Compile with g++ -std=c++0x libempty.cpp -o libempty.so -fPIC -shared
#include <iostream>
#include <vector>
using namespace std;
bool* g_finilized = nullptr;
struct Finilizer
{
    ~Finilizer()
    {
        cout << "~Finilizer()" << endl;
        if (g_finilized) *g_finilized = true;
    }
} g_finilizer;
class Base
{
public:
    virtual void init() = 0;
};
class Foo: public Base
{
    virtual void init()
    {
        static const vector<float> ns = { 0.f, 0.75f, 0.67f, 0.87f };
    }
};
extern "C" __attribute__ ((visibility ("default"))) Base* newBase() { return new Foo; }

Wenn ausgeführt, ist die Ausgabe:

false
false
~Finilizer()

Dies zeigt, dass der Aufruf von dlclose () nicht wie erwartet funktioniert und die Bibliothek erst beim Beenden des Programms entladen wurde.

Verschieben wir den Vektor jedoch nach außerhalb der Funktion, so lauten die letzten 8 Zeilen:

class Foo: public Base
{
    virtual void init()
    {
    }
};
static const vector<float> ns = { 0.f, 0.75f, 0.67f, 0.87f };
extern "C" __attribute__ ((visibility ("default"))) Base* newBase() { return new Foo; }

Dann funktioniert dlclose () richtig und die Ausgabe ist:

false
~Finilizer()
true

Die gleichen Ergebnisse werden generiert, wenn der Vektor in der Funktion verbleibt, aber keine Factory exportiert wird:

class Foo: public Base
{
    virtual void init()
    {
        static const vector<float> ns = { 0.f, 0.75f, 0.67f, 0.87f };
    }
};
//extern "C" __attribute__ ((visibility ("default"))) Base* newBase() { return new Foo; }

Positive Ergebnisse werden gefunden, wenn der Vektor durch ein C-Array ersetzt wird:

class Foo: public Base
{
    virtual void init()
    {
        static const float ns[] = { 0.f, 0.75f, 0.67f, 0.87f };
    }
};
extern "C" __attribute__ ((visibility ("default"))) Base* newBase() { return new Foo; }

Ist das ein Fehler in GCC / Linux? Gibt es eine Problemumgehung, mit der komplexe Objekte in der Mitgliedsfunktion einer faktorisierten Klasse als statisch deklariert werden können?

Antworten auf die Frage(1)

Ihre Antwort auf die Frage