Newsgroup: it.comp.lang.c++
Titolo: Ma xchè le string sono così difficili da usare?

Ciao a tutti.
Ho un problema con le string STL.
Il problema è questo.
Ho una classe ClasseStringa che al suo interno ha una var membro di nome
mNextString
Per accedervi uso un metodo public
void ClasseStringa::setNextString(string newString)
{
   mNextString = newString;
}
In un altro metodo d un'altra classe ho una var di tipo puntatore a 
ClasseStringa.
Eseguo le seguenti righe di codice :
[...]
string CIAO = "CIAO";
string TUTTI = "TUTTI";
[...]
m_pString->setNextString(CIAO);
[...]
m_pString->setNextString(TUTTI);
e nella seconda chiamata il compilatore mi da un ASSERT su
_CrtlsValidHeapPointer(pUserData) nel file dbgheap.c
Credo che vada a toccare una zona di memoria sporca dell'heap e non riesco a 
risolvere il problema. :o(
Come posso fare?
_________________________________________________________________________
Get Your Private, Free E-mail from MSN Hotmail at 
http://www.hotmail.com
.
-- 
Posted from [192.106.52.2] by way of 
law2-f97.hotmail.com
 [216.32.181.97] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

_CrtlsValidHeapPointer(pUserData) nel file dbgheap.c
Possiamo sapere che compilatore stai usando? E soprattutto stai usando
un compilatore C++?
Il Ghenio
-----
ZIO : Fun and games are over with. Anyone who dares
get in my way shall perish.
DIO ci salvi dagli ocx del Viral Basic.
-----

compilatore C++?
Scusa è vero. Uso il Visual C++ 6.0
Ho forse scoperto come mai l'errore, e mi sa che dalle informazioni che vi 
ho dato nn c potevate arrivare (ops!).
Ma ora vi chiedo il xchè faccia così!
La classe ClasseStringa è esportata in una dll. L'interfaccia che esponeva 
era con le string. La chiamata
m_pString->setNextString(CIAO)
viene fatta nel main che usa tale dll che espone questo metodo.
Ho il sospetto che nell'overload dell'operatore = lui usi l'area heap, ma 
che per ciò che gli passo (ad es CIAO) la new sia fatta nel main e la delete 
di questo nella dll ed ecco il perchè dell'assert. Come discorso è un pò 
contorto ma potrebbe essere così. Che ne pensate?
oPKo
_________________________________________________________________________
Get Your Private, Free E-mail from MSN Hotmail at 
http://www.hotmail.com
.
-- 
Posted from [192.106.52.2] by way of 
law2-f144.hotmail.com
 [216.32.181.144] 


 contorto ma potrebbe essere cosě. Che ne pensate?
Penso che le DLL di Windows sono state fatte per il C e non per il C++. Riuscire
a fare una DLL che contiene classi usate esternamente o che usa classi esterne
e' un casino immane e che non e' sempre possibile. Comunque ti "semplifichi" (si
fa per dire" la vita se i settaggi (e il codice) del tuo progetto sono quelli di
un prodotto multithreaded che linka la libreria standard dinamicamente (e non
staticamente).
--
Andrea Ferro
---------
Brainbench C++ Master. Scored higher than 97% of previous takers
Scores: Overall 4.46, Conceptual 5.0, Problem-Solving 5.0
More info 
http://www.brainbench.com/transcript.jsp?pid=2522556

e' un casino immane e che non e' sempre possibile.
Noi lo facciamo senza particolari problemi...
Luc.

"Luc" <TOGL...@katamail.com-TOGLI> wrote in message
news:qor6jt8gcmfhk44r9...@4ax.com...

Perche' sapete come farle. La prima volta che ci ho sbattuto la testa ci ho
impiegato parecchio a risolvere il problema. Peccato che era anni fa e non mi
ricordo piu' i dettagli.


 Noi lo facciamo senza particolari problemi...
mi puoi spiegare come fate?
io tempo fa ci ho provato (con VC++6.0) ma non ci sono riuscito.
grazie
--
ciao
xaero

contorto ma potrebbe essere così. Che ne pensate?
Problemi del Visual C++ , non certo delle std::string. Sono certo però
che con le CString funziona, visto che la M$ fa di tutto per impedirti
di usare la libreria standard nel suo compilatore.


Noi lo facciamo senza particolari problemi...
Io ho recentemente indagato sulla cosa dopo che un mio amico aveva
problemi a passare degli std::vector ad una DLL.
Quello che ho trovato e' che il VC++ non usa nessun meccanismo
speciale per le classi STL per evitare il problema di avere
diversi gestori di memoria. Addirittura anche senza fare
allocazioni/deallocazioni esplicite, container come std::map
non possono essere nemmeno usati in *read-only* da parte di una
DLL se sono stati costruiti all'esterno di questa.
Andando di debugger ho avuto l'impressione che i problemi in
quel caso siano dovuti ad elementi "sentinella" globali che
vengono istanziati via template e che quindi non vengono
riconosciuti nel codice compilato nella DLL (che avra', essendo
in pratica un programma intero e non una compilation unit,
un proprio elemento sentinella diverso da quello dell'exe).
Microsoft gestisce la cosa con i container MFC grazie ad una
chiamata specifica da fare nell'inizializzazione della DLL
per informare le librerie runtime di usare lo stesso gestore
memoria. Nella discussione sull'argomento i container STL
invece non vengono nemmeno citati (e questo fa pensare :) ).
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 invece non vengono nemmeno citati (e questo fa pensare :) ).
A me fa pensare solo al fatto che quando e' stata definita la MFC MS ha pensato
che avrebbe essere stato un bene poter usare le DLL e che quando e' stata
definito lo standard C++ il compitato non ha pensato molto a questo aspetto
particolare.
Dato che ne il VC ne l'implementazione delle STL che viene fornita con esso sono
ancora definitivi (anzi, l'ultima versione pubblica e' uscita prima che ci fosse
lo standard), dire che le STL di VC6 non vanno d'accordo con le DLL di windows
e' come dire che non vanno d'accordo con la partial template specialization.
Vero. Ma non significa nulla se non che sono un prodotto immaturo.
Purtroppo per avere tutto quello che si dovrebbe avere ci toccherą aspettare
VC8, ma questo e' un altro discorso.


 aspettare VC8, ma questo e' un altro discorso.
tanto + che deve ancora finire il 7....

toccherą aspettare VC8, ma questo e' un altro discorso.
Fammi indovinare... anche i preti potranno sposarsi ma
soltanto ad una certa eta' ? hehehe
Sai come si dice... "Una nuova versione sostituisce vecchi
bug noti con nuovi bug ignoti" :)))


 tanto + che deve ancora finire il 7....
Infatti. Anche se in realta' il compilatore C++ del 7 e' praticamente finito da
tempo (almeno la parte che riguarda la modalitą C++). Non e' ancora uscito
perche' fa parte di un pacchetto molto piu' complesso.


 soltanto ad una certa eta' ? hehehe
Esattamente.
-----------
Il problema delle DLL.
Oltre ad un certo numero di problemi di vario tipo legati al linguaggio per cui
usare il C++ con le DLL richiede come minimo l'usare la versione dinamicamente
della libreria standard, possibilmente multithreaded, esiste un problema
piuttosto grosso a livello dei template.
Esempio:
template <class T> class ATemplate {
public:
    void foo();
    static T t;
};
L'elemento incasinato e' il membro statico t.
Supponiamo che questo template sia usato da una DLL e che questa faccia
riferimento al t per una data classe. Domanda: la DLL deve istanziare il t o non
deve farlo? E lo deve inizializzare o no?
La risposta non e' affatto banale. Se decidiamo di non istanziarlo, la DLL
potrebbe essere linkata ad un programma dove non c'e' nessun'altro che fa uso di
quella variabile. Da questo dovremmo dedurre che il t va istanziato.
Ma a questo punto ci puo' essere un programma che a sua volta usa direttamente
il t (oltre ad usare la DLL). Se il programma lo istanzia a sua volta, finiamo
con l'avere due t distinti. Il programma potrebbe sapere a priori che il t e'
istanziato nella DLL e usare quello. Ma cosa succede se ci sono due DLL,
entrambe usano il t e vengono entrambe richiamate dal programma principale, ma
non sanno nulla l'una dell'altra?
Nel caso delle MFC il problema non e' cosi' grave dato che prima di usare le MFC
il programma e' obbligato a richiamare una apposita funzione di
inizializzazione. Inoltre tutte le MFC sono definite da MS. Pertanto esistono
metodi per gestire la cosa. Ma la soluzione delle MFC non si applica alla STL
(ne serve un'altra) a meno di non dire che il programma non puo' usare le STL
senza aver prima richiamato una data funzione di inizializzazione (poco standard
come idea) e inoltre bisognerebbe ridefinire parte dei template della STL.
Non sto dicendo che non sia possibile scrivere una STL usabile con le DLL. Sto
dicendo che non e' banale, non si puo' usare il tipo di soluzione adottato per
le MFC, e il risultato sarebbe meno performante sotto alcuni aspetti che non una
STL 'statica'. Pertanto ci dovrebbero essere due STL diverse, una piu' prestante
da usarsi solo in progetti statici, e una leggermente meno prestante da usarsi
in programmi che necessitano delle DLL.


e inoltre bisognerebbe ridefinire parte dei template della STL.
Sicuramente l'implementazione... non sono convinto che sarebbe
necessario rifare l'interfaccia di std::vector.
Quello che spesso la gente vorrebbe fare e' semplicemente avere
delle funzioni che accettino o ritornino un std::string... oppure
un std::map<int,std::string>& ... passare classi complesse (e
soprattutto user-defined) e' secondo me ragionevole che sia
piu' problematico e richieda regole precise.
Andrea
PS:
  Da parte mia la cosa non mi tocca molto... le DLL le uso
  solo quando mi serve il dinamismo di caricamento (cioe'
  raramente); quando posso preferisco creare degli eseguibili
  monoblocco "copy is installing" che non hanno nessuna DLL
  e che non usano nulla del registry.
  Raramente un mio utente si vedra' domandare:
    Il sistema contiene gia' la libreria xyz.dll che viene
    usata solamente per disegnare un effetto marmoreo sui
    bottoni. La versione presente e' pero' vecchiotta
    (risale addirittura a 6 settimane fa!) e usa una lingua
    diversa (aramaico). Si vuole sostituirla (e non far
    funzionare piu' i vecchi programmi) oppure non
    sostituirla (e non far funzionare questo programma) ?
  ;)


invece non vengono nemmeno citati (e questo fa pensare :) ).
Un collega mi ha detto che se aggiungi il link alle MFC, pur non
usando le MFC, "miracolosamente" anche la gestione della memoria
dentro le DLL migliora.
Secondo me si puo' tranquillamente affermare che la gestione della
memoria tra DLL ed EXE e' bacata con il VC, o comunque esageratamente
difficoltosa. Anche nei progetti multithread nutro sospetti, anche se
praticamente non sono mai riuscito a "dimostrare" la responsabilita'
di problemi ad eventuali bachi del gestore della memoria.
Personalmente, dopo averci sbattuto la testa, non scrivo piu' DLL in
C++ (possibilmente non scrivo piu' DLL) nei progetti, ed evito come la
peste di usare le librerie di debug del run-time.
Anche il tracciamento dei memory leak e' abbastanza triste. La
libreria stessa del VC perderebbe memoria.
-- 
Tieni per te il Papero giusto se vuoi la mia email
Sito Papero 1 -> 
http://utenti.tripod.it/papero
Sito Papero 2 -> 
http://user.7host.com/papero/

dinamiche (o per meglio dire fa finta di non saperlo).
per risolvere il problema e mantenere il programma portabile, il
compilatore potrebbe supportare qualcosa del tipo:
#pragma init_dynamic_stl
che richiama la funzione di inizializzazione proposta ad Andrea F.
Se un giorno dovremo portare il prog su un'altra piattaforma che non
supporta le lib dinamiche quel #pragma verrebbe ignorato e le potremmo
linkare staticamente.
Anto
--
Antonio Cuni, 19 anni, studente
Brainbench C++ Master: 4.6, higher than 98% of all previous test takers.
C Language: 3.32, higher than 79% of all previous test takers.
Guida C/C++ di Programmazione.it: 
http://cpp.programmazione.it

(solo) a MS... fuori di dubbio.
Da quello che ho potuto vedere infatti lo sviluppatore medio di VC++
non usa la STL, forse non sa neanche che cosa sia, sicuramente la
considera qualcosa non utile nei suoi progetti, perché la Microsoft
con la MFC fornisce dei container simili che ovviamente si integrano
molto meglio nel compilatore ma rendono il codice totalmente
dipendente dal sistema di sviluppo.
Inoltre con le MFC risulta spesso difficile, se non impossibile,
separare il nucleo del programma(ovvero ciò che si vuole rendere
standard e quindi portabile)da ciò che é l'interfaccia del programma
che dovrebbe invece essere ben distinta dal resto ed astratta il più
possibile. Spesso si é costretti a mescolare il tutto ottenendo
risultati funzionanti ma scadenti dal punto di vista qualitativo e con
codice difficilmente riutilizzabile qualora si volesse cambiare
sistema di sviluppo.
Ci sarebbe poi da fare un lungo discorso a riguardo della filosofia di
programmazione che l'uso degli wizard impone, ma da quello che ho
visto fin'ora c'é veramente da essere tristi.
Si ha spesso l'impressione che il programmatore perda completamente il
controllo su quello che sta facendo, che non capisca minimamente ciò
che lo wizard scrive e cosa sia necessario fare perché il programma
faccia ciò che si vuole, tanto che spesso si lascia tutto cosi' come é
perché non si é capaci minimamente di intervenire neanche per le cose
più semplici, come ad esempio sostituire l'icona principale del
programma.
Ovviamente tutte queste sono mie opinioni, poi ognuno è libero di
pensarla come vuole.


staticamente).
Facevo già così, e nn risolveva il problema.Grazie cmq x il consiglio. Alla 
fine ho esposto i metodi esportati come "const char *". In questo modo il 
tutto funziona (a parte che il .exe che usa la dll esce con un codice <>0, 
cioè 1244780, ma qsto nn è il NG giusto x parlarne).
Il sunto che ho tratto è che il VC++6.0 nn è adatto x qllo che dovrei 
realizzare ma essendo il prodotto che la ditta utilizza nn posso fare 
altrimenti. L'usare MFC nn è né una soluzione né una strada percorribile per 
molti motivi che nn è il caso di scrivere qui.
Sperando che la mail arrivi nel thread order corretto, ringrazio tutti per 
le risposte. Nn pensavo di creare una discussione così lunga :o), e anche 
così OT 8o( .
_________________________________________________________________________
Get Your Private, Free E-mail from MSN Hotmail at 
http://www.hotmail.com
.
-- 
Posted from [192.106.52.2] by way of 
law2-f14.hotmail.com
 [216.32.181.14] 


 linkare staticamente.
Non ci ho pensato a fondo. Ma credo che sia possibile una implementazione
completa della libreria standard (compresa la STL) che non richiede nulla del
genere. Una chiamata di inizializzazione generica alla DLL (ovvero una funzione
di inizializzazione della DLL dove non ci sono parametri) avviene sempre e
comunque. Il limite di dover linkare la libreria di sistema in versione dinamica
(non in versione statica) e' comunque sensato se intendi usare delle DLL. Queste
due cose sono sufficienti a creare un link fra main e DLL scritti da te
(attraverso la DLL di sistema che linkano entrambe).
Ovviamente la libreria di sistema non puo' fare uso di statiche templated.


 necessario rifare l'interfaccia di std::vector.
Infatti e' probabile che le STL finiscano con essere gestibili facilmente con le
DLL. Ma resta il problema che il linguaggio non e' facilmente gestibile con le


 visto fin'ora c'é veramente da essere tristi.
Conosco poco la MFC e il lato GUI dello sviluppo. Ma da quello che so il
probelma principale dei wizard e' che non hanno l'undo. Ovvero non permettono di
lavorare interattivamente. Ovvero presumono che ci sia un design solido a
priori.


 molte delle funzionalità della STL).
e qui non concordo io: vuoi mettere la comodita' di poter usare gli 
algoritmi sui contenitori/classi MFC? di solito cio' richiede di 
definire un iteratore per quel contenitore, ma non e' un grosso 
problema...

 non sanno nulla l'una dell'altra?
In effetti questo caso deve essere gestito esplicitamente, ovvero
bisogna garantire che per ciascuna specializzazione effettivamente
utilizzata esista una sola istanziazione dei relativi membri statici.
Col BCB e' possibile esportare da DLL specifiche istanziazioni di
template, e risolvere cosi' il problema.
Ciao,
Nicola

 che vanno piu' in la di qualche mese.
Per questo io ho aggiunto il "si suppone" fra parentesi. Che VC6 non sia
standard e che il VC7 lo sia in parte sono fatti (Ok che VC7 non e' uscito, ma
e' in beta avanzata e dubito che "tolgano" delle funzionalità per la release!).
Purtroppo pero' e' ancora un casino trovare un settaggio di flag che abiliti una
modalità "piu' standard possibile". In alcuni casi se vuoi la clompliance per un
certo aspetto ... devi rinunciarci per un altro. Questo e' in dibattimento
feroce da parte mia (e non solo) con MS. Ma non e' detto si risolva per l'uscita
di VC7. I motivi della scelta sono dovuti ai contrasti fra chi sta lavorando
alla compliancy e chi alla parte proprietaria. Il set di switch e' in
evoluzione. Si e' cercato di evitare che un set di flag che prima compilava in
un certo modo un certo codice, con la nuova versione non funzioni piu'. Per cui
il lato "extended" del compilatore ha dei flag per abilitare alcune compliancy.
Il lato "standard" al contrario e' standard per default. Purtroppo ci sono un
paio di funzionalità "compliant" abilitabili via flag nel settaggio
"proprietario" che non sono ancora presenti nella modalità "standard".


  e che non usano nulla del registry.
Una curiosita`: quando serve veramente il caricamento dinamico?
ciao
Kronos
-- 
Home: 
http://kronoz.cjb.net
The trouble with computers is that they do what you tell them, 
not what you want.
D. Cohen