PDA

View Full Version : [C++] Singleton class su Windows non vanno ???


trallallero
29-01-2008, 09:02
Quì è uscito un problema strano:
non a me ma ad un mio collega (che poverino sta programmando su Windows) non funzionano le classi Singleton, in pratica si trova 2 oggetti diversi della stessa classe, uno nel main e l'altro nella dll. C'è un tipo esperto che dice che su Windows non funziona la tecnica Singleton proprio per la gestione che ha il s.o. delle librerie dll.

C'è qualcuno che sa qualcosa a proposito ? il mio collega deve usare una variabile globale per risolvere il problema ...
Possibile non ci sia qualche trucco per ingannare il sistema in qualche modo ?

Eh, la potenza di Windows: i Singleton sono doppi :O

cionci
29-01-2008, 23:05
Mi sembra ovvio che non funzionino...su Linux funzionano i singleton con le librerie shared ?
Le librerie dinamiche hanno una vita separata dagli eseguibili che le usano e come tali anche una distinta fase di inizializzazione dei membri statici.

ilsensine
30-01-2008, 00:15
su Linux funzionano i singleton con le librerie shared ?
In genere sì. In genere.

trallallero
30-01-2008, 08:05
Mi sembra ovvio che non funzionino...su Linux funzionano i singleton con le librerie shared ?
Le librerie dinamiche hanno una vita separata dagli eseguibili che le usano e come tali anche una distinta fase di inizializzazione dei membri statici.

Si che funzionano perchè in Linux le librerie vengono caricate quando lanci l'eseguibile (lo vedi bene se fai una strace eseguibile)

In pratica windows col suo splendido sistema ha sfanculizzato qualche regola del C++. E immagino quindi che non funzioni neanche il sistema dei membri statici usati di solito come contatori se si utilizza qualche libreria dinamica

cionci
30-01-2008, 08:19
Allora...che il singleton funzioni all'interno della sola libreria statica mi sembra ovvio. Deve funzionare.

Forse ho capito male la questione...mi fai un esempio minimale (mi raccomando testalo, non solo riportando un pezzo del tuo codice, perché su queste cose bisogna avere il massimo della precisione per riuscire a venire a capo del problema) con il sorgente della dll e con il main ?

trallallero
30-01-2008, 08:34
Allora...che il singleton funzioni all'interno della sola libreria statica mi sembra ovvio. Deve funzionare.

Forse ho capito male la questione...mi fai un esempio minimale (mi raccomando testalo, non solo riportando un pezzo del tuo codice, perché su queste cose bisogna avere il massimo della precisione per riuscire a venire a capo del problema) con il sorgente della dll e con il main ?

il problema è questo
non a me ma ad un mio collega (che poverino sta programmando su Windows)
adesso glielo chiedo se ha qualcosa (è il tipo che ho convinto l'altra volta a sbloccare la sua read, non so se ricordi)

cionci
30-01-2008, 08:37
Sì mi ricordo...

fek
30-01-2008, 08:42
C'è qualcuno che sa qualcosa a proposito ? il mio collega deve usare una variabile globale per risolvere il problema ...

No, non deve usare una variabile globale perche' i Singleton non esistono su alcun sistema operativo :)

cionci
30-01-2008, 08:44
No, non deve usare una variabile globale perche' i Singleton non esistono su alcun sistema operativo :)
:asd:

trallallero
30-01-2008, 08:45
Allora...che il singleton funzioni all'interno della sola libreria statica mi sembra ovvio. Deve funzionare.

statica ? il problema non è nella lib statica ma se usi una classe singleton in un eseguibile e la stessa classe in una dll.
In pratica vengono create 2 istanze distinte.
Su Linux va, una sola istanza, su Windows no.
Il tutto è troppo complesso anche perchè il tipo sta lavorando in C++ (l'interfaccia che comunica con la mia Logica) ma deve comunicare con una libreria (Reflected Memory) scritta in C.

Io non ho capito bene cosa gli serva, mi ha solo esposto il problema dei singleton su windows e chiesto consigli: gli ho detto, usa i forum ;)

sto prendendo tempo, il tipo è sparito :D

cionci
30-01-2008, 08:48
Scusa, ho scritto statica al posto di dinamica.

Comunque guarda se ti fa un esempietto semplice in cui replica il problema. Altrimenti è difficile dare una risposta.

trallallero
30-01-2008, 08:50
No, non deve usare una variabile globale perche' i Singleton non esistono su alcun sistema operativo :)

spero tu abbia capito male ... ops, che io mi sia spiegato male :D

cionci
30-01-2008, 08:56
spero tu abbia capito male ... ops, che io mi sia spiegato male :D
fek ha un atavico odio verso i singleton. Condivisibile tra l'altro.

trallallero
30-01-2008, 08:57
Scusa, ho scritto statica al posto di dinamica.

Comunque guarda se ti fa un esempietto semplice in cui replica il problema. Altrimenti è difficile dare una risposta.

ah, ok.
Il tipo è tornato e sta scrivendo qualcosa ...

btw: non ho usato i command pattern per risolvere l'altro problema, ho risolto in maniera semplicissima (una semplice classe) perchè l'unico comando da eseguire in ritardo è spegnere un display.

ilsensine
30-01-2008, 09:06
Su Linux va, una sola istanza
Sì ma non contarci. A seconda di come è compilato e linkato lo shared object, potresti avere lo stesso identico comportamento che hai su windows.

cionci
30-01-2008, 09:11
btw: non ho usato i command pattern per risolvere l'altro problema, ho risolto in maniera semplicissima (una semplice classe) perchè l'unico comando da eseguire in ritardo è spegnere un display.
Ovvio...se è uno solo ;)

fek
30-01-2008, 09:20
spero tu abbia capito male ... ops, che io mi sia spiegato male :D

Ho capito bene e ti sei spiegato bene e i Singleton continuano a non esistere :)
Tanto e' vero che il tuo amico sta avendo problemi che si risolvono semplicemente implementando la soluzione senza il Singleton...

trallallero
30-01-2008, 09:25
Ho capito bene e ti sei spiegato bene e i Singleton continuano a non esistere :)
Tanto e' vero che il tuo amico sta avendo problemi che si risolvono semplicemente implementando la soluzione senza il Singleton...

infatti sta usando una variabile globale nel main, dichiarata extern nella libreria (se ho capito bene) ma preferirebbe non doverla usare (e lo capisco) e, da quello che dice, l'unico sistema sarebbe l'uso del singleton.

fek
30-01-2008, 09:28
infatti sta usando una variabile globale nel main, dichiarata extern nella libreria (se ho capito bene) ma preferirebbe non doverla usare (e lo capisco) e, da quello che dice, l'unico sistema sarebbe l'uso del singleton.

Il che dovrebbe subito far pensare al fatto che un Singleton non e' altro che una variabile globale mascherata e sdoganata ;)
Ma ne condivide tutti i problemi. Tolga del tutto la variabile globale e risolve i suoi problemi. Nel 99% dei casi ci vuole piu' tempo a dirlo che a farlo.

trallallero
30-01-2008, 09:36
Il che dovrebbe subito far pensare al fatto che un Singleton non e' altro che una variabile globale mascherata e sdoganata ;)
Ma ne condivide tutti i problemi. Tolga del tutto la variabile globale e risolve i suoi problemi. Nel 99% dei casi ci vuole piu' tempo a dirlo che a farlo.

non conosco bene il suo problema (ne ho già troppi io :D) ma gli serve una sola istanza ed una funzione statica perchè deve passare una callback (puntatore alla funzione statica, appunto) ad una libreria C.
Quindi, per garantire che ci sia una sola istanza, vorrebbe usare una classe Singleton.

Il tipo è sparito di nuovo ed io devo uscire a sbrigare qualche faccenda
Grazie, a dopo

fek
30-01-2008, 09:51
non conosco bene il suo problema (ne ho già troppi io :D) ma gli serve una sola istanza ed una funzione statica perchè deve passare una callback (puntatore alla funzione statica, appunto) ad una libreria C.
Quindi, per garantire che ci sia una sola istanza, vorrebbe usare una classe Singleton.

Il tipo è sparito di nuovo ed io devo uscire a sbrigare qualche faccenda
Grazie, a dopo

In realta' non gli serve sicuramente garantire che ci sia una sola istanza, gli serve che ne esista una sola nel suo processo. Sono due cose differenti. Comunque si puo' garantire che esista sia una sola istanza di una classe in un processo senza usare il Singleton pattern, quindi senza fare cose tipo:


UglySingleton* my_ugly_singleton = UglySingleton::GetInstance();

trallallero
30-01-2008, 10:47
In realta' non gli serve sicuramente garantire che ci sia una sola istanza, gli serve che ne esista una sola nel suo processo. Sono due cose differenti. Comunque si puo' garantire che esista sia una sola istanza di una classe in un processo senza usare il Singleton pattern, quindi senza fare cose tipo:


UglySingleton* my_ugly_singleton = UglySingleton::GetInstance();


ariecchime ...
io faccio solo da ambasciatore, non sono abituati ad usare forum quì, quindi se il tipo mi dice che gli serve il singleton avrà i suoi buoni motivi

Gli serve che ne esista una sola nel suo processo è corretto, ma se prova ad accedere all'oggetto dalla libreria dinamica e se non dichiara l'oggetto come variabile globale, non funziona.

Comunque aggiorno quando mi fanno avere un esempio ... hanno provato anche ad usare un membro statico settato a 5 nel main.
La libreria lo visualizza come 0

E io ho ritenuto giusto appiccicare l'adesivo "Certified for Windows Vista" del nuovo monitor sul gabicesso :asd:

UglySingleton ... non te piacciono proprio eh :D

fek
30-01-2008, 11:26
ariecchime ...
io faccio solo da ambasciatore, non sono abituati ad usare forum quì, quindi se il tipo mi dice che gli serve il singleton avrà i suoi buoni motivi

Quante volte l'ho sentito dire :D
Ed i buoni motivi erano spesso una cosa del tipo "non so farlo in altro modo".

trallallero
30-01-2008, 11:38
Quante volte l'ho sentito dire :D
Ed i buoni motivi erano spesso una cosa del tipo "non so farlo in altro modo".

beh, probabile, nessuno sa tutto ;)

Resta il fatto che su Windows non va ... sto aspettando ancora il test, son tutti a pranzo.

fek
30-01-2008, 11:49
beh, probabile, nessuno sa tutto ;)

Assolutamente, e c'e' chi ha voglia di imparare e chi invece va dritto per l'unica strada che conosce...

banryu79
30-01-2008, 11:51
Comunque si puo' garantire che esista sia una sola istanza di una classe in un processo senza usare il Singleton pattern, quindi senza fare cose tipo:


UglySingleton* my_ugly_singleton = UglySingleton::GetInstance();

C'è una strategia canonica per sostituire/rifattorizzare i Sigleton?
In tal caso avresti un link da postare? Interesserebbe anche a me, grazie.

Scusate l'OT

@EDIT:

Quella più semplice è portarsi dietro un parametro ovunque venga richiamato il singleton.

Perdonami, ma temo di non aver capito... puoi esplicitare ulteriormente la cosa?

cionci
30-01-2008, 11:54
Quella più semplice è portarsi dietro un parametro ovunque venga richiamato il singleton.

fek
30-01-2008, 12:10
Quella più semplice è portarsi dietro un parametro ovunque venga richiamato il singleton.

Yup, di solito faccio cosi' e da' meno problemi di quello che sembra.

MEMon
30-01-2008, 12:22
Ragazzi scusate se mi intrometto, ma quando dovrebbe venire utile un singleton?
Cioè per quali scopi solitamente si usano? Ora come ora non riesco a pensare dove lo userei...

cionci
30-01-2008, 12:29
Perdonami, ma temo di non aver capito... puoi esplicitare ulteriormente la cosa?
Cioè...in MyClass mi serve un singleton ? Allora passo l'istanza della classe che una volta era il singleton nel costruttore (se mi serve in molti metodi) o come parametro di un metodo.

class MyClass
{
public:
MyClass(MyExSingleton &param);
//oppure
void MyPublicMethod(MyExSingleton &param);
};
In pratica si sostituisce la chiamata alla GetInstance del singleton con un parametro del metodo o della classe.
Ovviamente questo non garantisce che non ci siano più istanze di MyExSingleton nel sistema, ma se il progetto è ben scritto (e guidato) basta propagare MyExSingleton a poche classi.

fek
30-01-2008, 12:32
Ragazzi scusate se mi intrometto, ma quando dovrebbe venire utile un singleton?

In tutti i seguenti casi:

cionci
30-01-2008, 12:33
Ragazzi scusate se mi intrometto, ma quando dovrebbe venire utile un singleton?
Cioè per quali scopi solitamente si usano? Ora come ora non riesco a pensare dove lo userei...
Il singleton può prendere il posto di qualsiasi variabile globale che contiene un riferimento o un puntatore ad un oggetto.
Se poi ti chiedi: mi hanno sempre insegnato che non si usano le variabili globali nella programmazione OOP, allora ti sei risposto da solo alla domanda: quando posso usare un singleton ? :D

MEMon
30-01-2008, 12:33
In tutti i seguenti casi:

:D
No dai sul serio, riformulo la domanda.
Quali problemi portano a pensare ad una prima soluzione utilizzando i singleton, ma poi pensandoci bene si risolvono anche in altri modi?

MEMon
30-01-2008, 12:34
Il singleton può prendere il posto di qualsiasi variabile globale che contiene un riferimento o un puntatore ad un oggetto.
Se poi ti chiedi: mi hanno sempre insegnato che non si usano le variabili globali nella programmazione OOP, allora ti sei risposto da solo alla domanda: quando posso usare un singleton ? :D
Perfetto afferato il discorso!

fek
30-01-2008, 12:34
:D
No dai sul serio, riformulo la domanda.
Quali problemi portano a pensare ad una prima soluzione utilizzando i singleton, ma poi pensandoci bene si risolvono anche in altri modi?

Ma ero serio :D

cionci
30-01-2008, 12:35
fek: però mi sono chiesto...in un DLL condivisa fra più eseguibili, come faccio ad accedere ad una istanza condivisa di una classe (allocata da DllMain) se non uso una variabile static o un singleton o una variabile globale ?

banryu79
30-01-2008, 12:35
Grazie mille del chiarimento cionci, ho capito la mia non comprensione da cosa era nata:

Ovviamente questo non garantisce che non ci siano più istanze di MyExSingleton nel sistema, ma se il progetto è ben scritto (e guidato) basta propagare MyExSingleton a poche classi


Avendo letto in precedenza questo:

Comunque si puo' garantire che esista sia una sola istanza di una classe in un processo senza usare il Singleton pattern, quindi senza fare cose tipo:
UglySingleton* my_ugly_singleton = UglySingleton::GetInstance();

mi stavo chiedendo quale fosse quella strategia che mi evita l'uso del Singleton E mi garantisce una sola istanza di classe.

Si può fare senza classe Singleton? :confused:

fek
30-01-2008, 12:39
fek: però mi sono chiesto...in un DLL condivisa fra più eseguibili, come faccio ad accedere ad una istanza condivisa di una classe (allocata da DllMain) se non uso una variabile static o un singleton o una variabile globale ?

Hmmm, mi fai un esempio piu' concreto?
Secondo me il problema e' piu' di design: perche' devi accedere da piu' eseguibili ad una istanza condivisa e non puoi usare metodi di comunicazione fra processi piu' affidabili?


mi stavo chiedendo quale fosse quella strategia che mi evita l'uso del Singleton E mi garantisce una sola istanza di classe.

Si può fare senza classe Singleton? :confused:


Di nuovo, perche' ti serve garantire una sola istanza di una classe? In questo caso io mettere una variabile statica nella classe e il costruttore forzerebbe il numero di istanze in base a quella variabile, restituendo un eccezione.
Non si avrebbero i problemi creati da quell'orribile getInstance(), ma si continuerebbero ad avere tutti i problemi legati alla testabilita' dei Singleton.

trallallero
30-01-2008, 12:43
ok, in allegato il test fatto con Visual studio.

Ho visto l'output e sembra da una parte funzionare (l'indirizzo della funzione statica è lo stesso sia printato dal main che dalla dll) da un'altra no:

c'è, nella classe singleton, una variabile statica int querty = 5
nel main è settata a 7

poi viene printeffata dal main, ed è 7,
dalla libreria statica è 7
dalla dll è 97534 ...

comunque anche wikipedia (in tedesco) dice che i singleton non vanno su Windows

trallallero
30-01-2008, 12:49
Di nuovo, perche' ti serve garantire una sola istanza di una classe? In questo caso io mettere una variabile statica nella classe e il costruttore forzerebbe il numero di istanze in base a quella variabile, restituendo un eccezione.
Non si avrebbero i problemi creati da quell'orribile getInstance(), ma si continuerebbero ad avere tutti i problemi legati alla testabilita' dei Singleton.

è esattamente quello che ho fatto io in una classe di questo progetto, anche se poi l'ho eliminata e modificato il design.

Quì volevano farmi usare il singleton anche su una classe di string utilities che ho fatto. Io ho messo tutte le funzioni statiche in modo da poterle utilizzare così:
Utility::Funzione(...)
e loro m'han detto, "il singleton è meglio" ... mi son rifiutato :O

perchè devo creare un'istanza con quel giro di beppe quando ci pensa il C++ automaticamente con le sue funzioni statiche ?

fek
30-01-2008, 12:53
è esattamente quello che ho fatto io in una classe di questo progetto, anche se poi l'ho eliminata e modificato il design.

Quì volevano farmi usare il singleton anche su una classe di string utilities che ho fatto. Io ho messo tutte le funzioni statiche in modo da poterle utilizzare così:
Utility::Funzione(...)
e loro m'han detto, "il singleton è meglio" ... mi son rifiutato :O

perchè devo creare un'istanza con quel giro di beppe quando ci pensa il C++ automaticamente con le sue funzioni statiche ?

Hai fatto bene :)
In quella situazione una classe completamente statica va benissimo. Anche solo il namespace va bene secondo me, ma qualche purista non e' d'accordo (e ci sono buoni argomenti a favore di questa posizione).

cionci
30-01-2008, 13:01
Era proprio quello che pensavo avesse fatto :D Sicuro che su Linux funzioni un codice simile ?
Imho è impossibile...come fa Singleton della DLL ad avere in comune con la Singleton del main lo stesso indirizzo a cui è allocato il membro statico ?
In quel caso i due codici sono completamente non comunicanti. L'unico modo per mettere in comunicazione il main e la DLL è attraverso i simboli esportati.
Se vuoi creare un Singleton nella DLL lo dove esportare e devi far riferimento al simbolo esportato da dentro il main e non puoi comunque far riferimento ad una Singleton importata tramite include e pensare che agendo su quella tu agisca anche su quella esportata dalla DLL perché ancora hanno istanze diverse dei membri static.

cionci
30-01-2008, 13:03
Hai fatto bene :)
Io odio profondamente le classi all-static...se con i singleton si aggirano le variabili globali con le classi all-static si aggirano le funzioni globali :eek:

fek
30-01-2008, 13:12
Io odio profondamente le classi all-static...se con i singleton si aggirano le variabili globali con le classi all-static si aggirano le funzioni globali :eek:

Ma le funzioni globali non sono affatto un problema :)

Preferisco qualcosa tipo:


namespace Math
{

float pow(float x)
{
...
}

}


A orrori del calibro di:


class MathStuff
{
public:
float pow(float x)
{
...
}
};


Sono sempre per il fare le cose semplici. I dati globali, al contrario, sono un problema proprio perche' non e' mai chiaro chi li manipola e quando.

trallallero
30-01-2008, 13:13
Era proprio quello che pensavo avesse fatto :D Sicuro che su Linux funzioni un codice simile ?
assolutamente si. QUEL codice non lo so, non l'ho fatto io (su Windows ci avrei messo 2 giorni :D) ma su Linux, lib e main comunicano allegramente senza problemi. Scusa ma che differenza c'è nel dichiarare una variabile globale nel main e poi usarla extern nella lib ?

Comunque la variabile querty ho visto che l'hanno esportata.

banryu79
30-01-2008, 13:14
Di nuovo, perche' ti serve garantire una sola istanza di una classe? In questo caso io mettere una variabile statica nella classe e il costruttore forzerebbe il numero di istanze in base a quella variabile, restituendo un eccezione.
Non si avrebbero i problemi creati da quell'orribile getInstance(), ma si continuerebbero ad avere tutti i problemi legati alla testabilita' dei Singleton.
Ok, grazie.
Lo terrò a mente nel caso in cui mi imbatta in una simile necessità in futuro, evitando di farmi la classe Singleton.

Per quanto riguarda i problemi del getInstance(), non ne so nulla, però proprio in questi giorni sto lavorando su del codice scritto da un collega che ha utilizzato una classe per wrappare un set di query a un db.

Ora quando io voglio interagire col db non posso crearmi localmente un'istanza con new, ma sono costretto a chiamare getInstance() per poter accedere ai metodi (non statici) di quella classe.

A questo punto mi chiedo quali siano i potenziali problemi con questo scenario?

cionci
30-01-2008, 13:16
assolutamente si. QUEL codice non lo so, non l'ho fatto io (su Windows ci avrei messo 2 giorni :D) ma su Linux, lib e main comunicano allegramente senza problemi. Scusa ma che differenza c'è nel dichiarare una variabile globale nel main e poi usarla extern nella lib ?
Con una libreria statica lo puoi fare, con una dinamica non credo, anche se non ho mai provato (anzi sono quasi sicuro di no).
In ogni caso gli export sono questi:

LIBRARY DLL_PART

EXPORTS

testDllFunc = ?testDllFunc@@YAXXZ

fek
30-01-2008, 13:22
Ora quando io voglio interagire col db non posso crearmi localmente un'istanza con new, ma sono costretto a chiamare getInstance() per poter accedere ai metodi (non statici) di quella classe.

A questo punto mi chiedo quali siano i potenziali problemi con questo scenario?

Innanzi tutto non sai mai di preciso chi invoca getInstance() per primo quindi chi crea per primo l'istanza della classe, ed in progetti di grandi dimensioni questo e' un notevole problema, soprattutto quando diversi Singletone devono essere creati in un certo ordine, perche' uno dipende dall'altro. Che brutti ricordi.

Poi in scenari multitasking scrivere una versione di getInstance() thread safe e' un problema ENORME.

Usando i Singleton in C++ e' molto difficile controllare il ciclo di vita di un oggetto: chi lo distrugge? E quando?

Questo senza toccare i problemi legati al testare un Singleton.

trallallero
30-01-2008, 13:27
Con una libreria statica lo puoi fare, con una dinamica non credo, anche se non ho mai provato (anzi sono quasi sicuro di no).
In ogni caso gli export sono questi:

LIBRARY DLL_PART

EXPORTS

testDllFunc = ?testDllFunc@@YAXXZ

ok, grazie.

Ma l'hai testato il codice ?
come si spiega che l'indirizzo della funzione statica stampato dal main coincida con quello stampato dalla dll ? anche perchè NON dovrebbe essere così secondo quanto letto in rete.

banryu79
30-01-2008, 13:41
Innanzi tutto non sai mai di preciso chi invoca getInstance() per primo quindi chi crea per primo l'istanza della classe, ed in progetti di grandi dimensioni questo e' un notevole problema, soprattutto quando diversi Singletone devono essere creati in un certo ordine, perche' uno dipende dall'altro. Che brutti ricordi.

Mmm, interessante. Per fortuna non è il mio caso (progetto di medie-piccole dimensioni, nessuna dipendenza tra Singleton)


Poi in scenari multitasking scrivere una versione di getInstance() thread safe e' un problema ENORME.

Ok, non mi sono ancora mai cimentato in progetti reali multithreading e non è questo il caso, ma pensavo bastasse rendere synchronized la classe o il metodo.


Usando i Singleton in C++ e' molto difficile controllare il ciclo di vita di un oggetto: chi lo distrugge? E quando?

Ok.


Questo senza toccare i problemi legati al testare un Singleton.

Mi interesserebbe capire questo aspetto, esiste della lettera?

Grazie dei chiarimenti :)

fek
30-01-2008, 14:02
Mi interesserebbe capire questo aspetto, esiste della lettera?

Grazie dei chiarimenti :)

Figurati :)
http://www.hwupgrade.it/forum/showthread.php?t=1664835

cionci
30-01-2008, 14:15
Purtroppo non sono sotto Windows e non posso provare.

Intendi l'output di questa istruzione ?
std::cout << "Singleton address inside main.cpp " << &(Singleton::instance()) << std::endl;
Imho puro caso...mi spiego: il posizionamento nello stack dei membri statici avviene a tempo di compilazione in funzione dell'ordine di linking degli stessi.
Qui c'è un solo membro statico da posizionare sia per il main che per la dll e viene posizionato nello steso posto.
Se crei Singleton2.cpp e Singleton2.h (andando a sostituire il nome in ogni occorrenza di Singleton) e lo linki al main prima di Singleton.cpp vedrai che l'istanza di Singleton nel main e quella di Singleton della DLL avranno indirizzi diversi !!!

In ogni caso quello che è stato fatto con la DLL non è assolutamente un Singleton ...le classi Singleton del main e della DLL hanno istanze disgiunte della classe singleton e quindi non comunicanti. Se vuoi lavorare su una sola classe singleton deve esportare una qualche funzione che ritorna l'istanza della classe singleton istanziata nella DllMain...altrimenti qualsiasi altra macchinazione è senza senso.

PS: mi fai vedere come lo faresti in Linux perché, se funziona, scommetto che non ci sono analogie con questa.
PPS: io i singleton in C++ li ho sempre visti instanziare con una new, dubito che l'istanza statica funzioni se il membro statico non è anch'esso esportato

trallallero
30-01-2008, 15:01
Purtroppo non sono sotto Windows e non posso provare.

Intendi l'output di questa istruzione ?
std::cout << "Singleton address inside main.cpp " << &(Singleton::instance()) << std::endl;
Imho puro caso...mi spiego: il posizionamento nello stack dei membri statici avviene a tempo di compilazione in funzione dell'ordine di linking degli stessi.
Qui c'è un solo membro statico da posizionare sia per il main che per la dll e viene posizionato nello steso posto.
Se crei Singleton2.cpp e Singleton2.h (andando a sostituire il nome in ogni occorrenza di Singleton) e lo linki al main prima di Singleton.cpp vedrai che l'istanza di Singleton nel main e quella di Singleton della DLL avranno indirizzi diversi !!!

In ogni caso quello che è stato fatto con la DLL non è assolutamente un Singleton ...le classi Singleton del main e della DLL hanno istanze disgiunte della classe singleton e quindi non comunicanti. Se vuoi lavorare su una sola classe singleton deve esportare una qualche funzione che ritorna l'istanza della classe singleton istanziata nella DllMain...altrimenti qualsiasi altra macchinazione è senza senso.

PS: mi fai vedere come lo faresti in Linux perché, se funziona, scommetto che non ci sono analogie con questa.
PPS: io i singleton in C++ li ho sempre visti instanziare con una new, dubito che l'istanza statica funzioni se il membro statico non è anch'esso esportato

beh non so cosa abbiano fatto, non l'ho neanche visto il codice, ma pensavo avessero fatto una new instance.
Io non ho mai fatto un singleton in vita mia quindi non so come lo farei su linux.
Di certo mi aspetto che un membro statico di una determinata classe sia lo stesso visto dal main che dalla libreria, cosa che non succede su windows
Se vuoi ti faccio un esempio

trallallero
30-01-2008, 15:34
per esempio, non singleton ma semplice membro statico, su linux questo va:

file main.h

#ifndef MAIN_H_
#define MAIN_H_

#include <iostream>

using namespace std;

class test
{
public:
test() {}

static int m_x;
};

#endif /*MAIN_H_*/


file main.cpp

#include <iostream>
#include "main.h"

extern void PrintLibX();

int test::m_x = 1;

test t;

int main()
{
cout << "print from main -> m_x: " << test::m_x << endl;
test::m_x = 5;
cout << "print from main -> m_x: " << test::m_x << endl;

PrintLibX();
}

file lib.cpp
#include "main.h"

void PrintLibX()
{
cout << "test::m_x: " << test::m_x << endl;
}


per compilare:
g++ -c -g3 -Wall -o lib.o lib.cpp
g++ -shared -Wl,-soname,libTest.so -o libTest.so lib.o
g++ -g main.cpp -L. -lTest -o mainprint from main -> m_x: 1
print from main -> m_x: 5
print from lib -> test::m_x: 5


eseguo:
./main

output:
print from main -> m_x: 1
print from main -> m_x: 5
print from lib -> test::m_x: 5


in pratica su windows questo non va perchè il main e la dll risiedono su memorie diverse. Ed è il problema che è alla base dei singleton

PS: ho messo i files in allegato

cionci
30-01-2008, 15:39
Di certo mi aspetto che un membro statico di una determinata classe sia lo stesso visto dal main che dalla libreria, cosa che non succede su windows
Non lo è nemmeno su Linux fatto così, stanne sicuro. Credo che ilsensine possa confermare.

Sono due membri statici diversi perché appartenenti a due istanze diverse.

Trallellero: avete fatto due cose diverse. Tu hai linkato il tuo eseguibile alla libreria dinamica (il riferimento alla variabile static viene già tradotto come un riferimento esterno alla libreria dinamica), non hai caricato la libreria dinamica a runtime come nell'esempio su Windows.

ilsensine
30-01-2008, 15:46
Non lo è nemmeno su Linux fatto così, stanne sicuro. Credo che ilsensine possa confermare.

Sono due membri statici diversi perché appartenenti a due istanze diverse.
Credo che c'è un pò di confusione. Una cosa è _dichiarare_ la classe e il suo membro statico in un .h, un'altra è implementare il membro statico dentro qualche file cpp.
Per me il problema del collega di Trallallero è uscito fuori perché è stato fatto in qualche modo un programma _e_ una dll ciascuno con una sua istanza del membro. In questo caso su linux "sembra" funzionare, ma - ripeto - dipende da alcuni fattori.
Riguardo all'esempio precedente, c'è una sola istanza di m_x. Peraltro fuori della libreria, che si ritrova quindi un simbolo non risolto. Credo che in questa situazione fare una dll è impossibile, in quanto le dll non ammettono simboli non risolti da quel che ne so...

cionci
30-01-2008, 15:50
ilsensine: il collega ha caricato la DLL con una istanza statica di Singleton a runtime con LoadLibrary (dlopen su Linux) e con GetProcAddress (dlsym su Linux) ha richiamato la funzione di stampa che opera sul Singleton. Il Singleton è già istanziata all'interno del main ed è linkato staticamente all'eseguibile, come fanno a condividere lo stesso indirizzo anche volendo ??? :D

PS: il simbolo non risolto è nel main, non nella DLL ;)

ilsensine
30-01-2008, 15:56
ilsensine: il collega ha caricato la DLL con una istanza statica di Singleton a runtime con LoadLibrary e con GetProcAddress ha richiamato la funzione di stampa. Singleton è già istanziata all'interno del main ed è linkata staticamente all'eseguibile, come fanno a condividere lo stesso indirizzo anche volendo ??? :D
Sarei curioso di vedere il codice, ma:
- L'applicazione ha instanziato un singleton? Ok allora c'è da qualche parte una variabile o un membro statico che ne contiene il puntatore all'istanza.
- La Dll è stata compilata? Allora non ci sono simboli non risolti (attendo conferma di questo -- Fek?) ed essa stessa ha quindi una sua copia di questa fantomatica variabile.

Ho paura che l'origine del problema sia questa.

cionci
30-01-2008, 16:03
Ho paura che l'origine del problema sia questa.
Nemmeno il main ha simboli irrisolti...il fatto è questo. Sia il main che la DLL hanno la loro copia statica di Singleton (comunque guarda il codice, è stato postato ;)).

ilsensine
30-01-2008, 16:08
Nemmeno il main ha simboli irrisolti...il fatto è questo. Sia il main che la DLL hanno la loro copia statica di Singleton (comunque guarda il codice, è stato postato ;)).
Quela? Questo?
http://www.hwupgrade.it/forum/showpost.php?p=20833117&postcount=39
Prima vorrei sapere per certo se il _singolo_ file "static_part.cpp" può diventare da solo una Dll, in quanto ha riferimenti non risolti ai metodi di Singleton, senza che la Dll sia linkata a qualcuno che fornisce quei simboli.

Su linux puoi farlo (pratica discutibile ma possibile), ma su windows mi sembra di no.

cionci
30-01-2008, 16:13
No...stai sicuro che viene linkato anche Singleton.cpp ;)

ilsensine
30-01-2008, 16:13
No...stai sicuro che viene linkato anche Singleton.cpp ;)
...e allora ti sei risposto da solo. E conosco anche il modo per ottenere lo stesso comportamento sotto linux.

trallallero
30-01-2008, 16:19
mi sa che è tardi per me, non c'ho capito un cacchio di ciò che avete scritto :stordita:

trallallero
30-01-2008, 16:21
Credo che in questa situazione fare una dll è impossibile, in quanto le dll non ammettono simboli non risolti da quel che ne so...

o marò ! :eek:
ma che davero ?

cionci
30-01-2008, 16:27
o marò ! :eek:
ma che davero ?
Le dll, ma te il simbolo non risolto l'hai messo nel main, giustamente ;)

trallallero
30-01-2008, 16:33
Le dll, ma te il simbolo non risolto l'hai messo nel main, giustamente ;)

void PrintLibX()
{
cout << "print from lib -> test::m_x: " << test::m_x << endl;
}

nella lib test::m_x non è risolto. La lib non sa neanche cosa sia ma la creo lo stesso senza errori

cionci
30-01-2008, 17:30
nella lib test::m_x non è risolto. La lib non sa neanche cosa sia ma la creo lo stesso senza errori
Non avevo visto che non l'avevi linkato. Mai visto un utilizzo del genere, in ogni caso il codice fatto dal tuo collega è molto diverso dal tuo. Infatti carica a runtime la dll !!!

^TiGeRShArK^
30-01-2008, 17:51
Hai fatto bene :)
In quella situazione una classe completamente statica va benissimo. Anche solo il namespace va bene secondo me, ma qualche purista non e' d'accordo (e ci sono buoni argomenti a favore di questa posizione).

Allora possiamo usare anche la mia classe statica per gestire le properties in diamonds dato che non è effettivamente un Singleton poichè non ritorna nessuna istanza, ma garantisce (ora come ora) che la configurazione per l'intero progetto sia uguale per tutte le classi che vi accedono (utilizzando solo metodi statici)... il che sinceramente mi pare + un pregio che un difetto.. :mbe:
link:
http://www.hwupgrade.it/forum/showpost.php?p=20818025&postcount=3

fek
30-01-2008, 19:58
Allora possiamo usare anche la mia classe statica per gestire le properties in diamonds dato che non è effettivamente un Singleton poichè non ritorna nessuna istanza,

Ti spezzo il legamento crociato anteriore del ginocchio. Cosi' puoi ancora programmare, ma ti fara' una male cane.

^TiGeRShArK^
30-01-2008, 21:01
Ti spezzo il legamento crociato anteriore del ginocchio. Cosi' puoi ancora programmare, ma ti fara' una male cane.
ahia.. :cry:

trallallero
31-01-2008, 07:52
Non avevo visto che non l'avevi linkato. Mai visto un utilizzo del genere, in ogni caso il codice fatto dal tuo collega è molto diverso dal tuo. Infatti carica a runtime la dll !!!

vabbè, fatti suoi. Ormai mi ha detto che ha quasi finito quindi avrà risolto in qualche modo.
Io per fortuna lavoro su Linux e 'sto problemi di dll non ne ho.
Grazie di nuovo a tutti :)

thebol
31-01-2008, 09:54
Ti spezzo il legamento crociato anteriore del ginocchio. Cosi' puoi ancora programmare, ma ti fara' una male cane.
Non fa un male cane. Si sente solo un piccolo stack, come quando ci si fa schioccare un osso. (sigh)

ndakota
31-01-2008, 13:31
per il ragazzo che ha scritto in che casi andasse usato: il libro design patterns recita:

il pattern singleton può essere usato:
- quando deve esistere esattamente un'istanza di una classe e tale istanza deve essere resa accessibile ai client attraverso un punto di accesso noto a tutti gli utilizzatori;

- quando l'unica istanza deve poter essere estesa attraverso definizione di sottoclassi e i client devono essere in grado di utilizzare le istanze estese senza dover modificare il proprio codice.

poi ne parla per 7/8 pagine..

chi vorrebbe muovere una critica nei miei confronti sappi che non ho la minima idea di quello che ho detto ma che mi sono limitato a ricopiare dal libro :D

trallallero
31-01-2008, 13:35
Non fa un male cane. Si sente solo un piccolo stack, come quando ci si fa schioccare un osso. (sigh)
si vabbè, 5, 10 secondi ... poi urli come un ossesso ;)

che vorrebbe muovere una critica nei miei confronti sappi che non ho la minima idea di quello che ho detto ma che mi sono limitato a ricopiare dal libro :D
:D

banryu79
31-01-2008, 13:35
per il ragazzo che ha scritto in che casi andasse usato:
... omissis


No-no, leggi il link che ha postato fek, i casi corretti in cui usare un Singleton sono i seguenti:
.

Ciao :D

thebol
31-01-2008, 13:35
per il ragazzo che ha scritto in che casi andasse usato: il libro design patterns recita:

il pattern singleton può essere usato:
- quando deve esistere esattamente un'istanza di una classe e tale istanza deve essere resa accessibile ai client attraverso un punto di accesso noto a tutti gli utilizzatori;

- quando l'unica istanza deve poter essere estesa attraverso definizione di sottoclassi e i client devono essere in grado di utilizzare le istanze estese senza dover modificare il proprio codice.

poi ne parla per 7/8 pagine..

chi vorrebbe muovere una critica nei miei confronti sappi che non ho la minima idea di quello che ho detto ma che mi sono limitato a ricopiare dal libro :D

penso che gli autori stiano ancora mangiandosi le mani per averlo inserito nel gof :asd:

fek
31-01-2008, 13:38
penso che gli autori stiano ancora mangiandosi le mani per averlo inserito nel gof :asd:

Gia', piu' volte hanno affermato che e' stato un errore :)

thebol
31-01-2008, 13:40
si vabbè, 5, 10 secondi ... poi urli come un ossesso ;)


:D
si ma non per il legamento, ma per il ginocchio che di solito ha fatto un brutto movimento.

io dopo meno di un ora sono tornato a casa in macchina guidando io. E mi sono accorto che era rotto dopo mesi che il ginocchio non tornava piu stabile come prima.

btw fine ot :\

thebol
31-01-2008, 13:44
Gia', piu' volte hanno affermato che e' stato un errore :)
gia, anchè perchè da quel che ho letto molti affermavano di sapere i pattern sapendo quasi solo il singletone :asd:

trallallero
05-02-2008, 07:43
Secondo me il problema e' piu' di design: ....
ecco, avevi ragione, mi ha detto che ha risolto senza singletone grazie ad un'idea di un nostro collega (non so come)
Modificato il design, via il singleton :)

fek
05-02-2008, 10:41
ecco, avevi ragione, mi ha detto che ha risolto senza singletone grazie ad un'idea di un nostro collega (non so come)
Modificato il design, via il singleton :)

Adoro i piani ben riusciti :D

trallallero
05-02-2008, 10:46
Adoro i piani ben riusciti :D

:D

beh fa 26 anni oggi il ragazzo, molto in gamba ma ancora in erbe :asd: