Newsgroup: it.comp.lang.c++
Titolo: [help] try

 >TCPStream * pTcp = 0;
 >try {
 >  pTcp = new TCPStream(addr,666);
 >  pTcp->isPending(SOCKET_PENDING_INPUT);
 >}
 >catch (TCPStream::Ctor_err) {
 >//blablabla
 >  delete pTcp;
 >  pTcp=0;
 >}
 >catch (...) {
 >/*blablabla*/
 >  delete pTcp;
 >  pTcp=0;
 >}
La delete non e` necessaria, se il costruttore lancia una eccezione,
la memoria allocata da new e` automaticamente rilasciata (un altro
motivo per preferire new a malloc...)
Bisogna osservare infine che l'uso del puntatore elimina la necessita`
di racchiudere tutto il codice in un try/catch, ma introduce un'altra possibile
fonte di eccezione: la new potrebbe infatti sollevare una std::bad_alloc
(nell'altra soluzione e` tuttavia possibile anche uno stack overflow).
Paolo
--
Paolo Marotta
Duck Communication Entertainment s.r.l.
Largo Arenula, 11 - Roma
http://www.duckce.com
p.ma...@duckce.com
-- 
Posted from 
HA-server-a.cs.interbusiness.it
 [151.99.250.31] 
via Mailgate.ORG Server - 
http://www.Mailgate.ORG

Piu' o meno corretta l'idea di usare la classe allocata dinamicamente. E
infatti il problema nasce da una classe mal progettata.
Scopo di un costruttore è rendere stabile una classe. Ovvero far si che
i suoi membri siano coerenti con la logica di funzionamento. 
Per una classe che rappresenta uno stream TCP come sembra sia il caso,
lo scopo del costruttore è creare la classe, non creare e aprire lo
stream. La classe, se ben disegnata, conterrà funzioni di open e close
dello stream e funzioni di query dello stato (aperto/chiuso).
Quindi prima si crea lo stream, poi si chiama la open.
In alternativa è possibile anche passare dei parametri di
inizializzazione al costruttore in modo che questo possa anche aprire lo
stream. Ma un costruttore dovra' prima creare la classe e POI aprire lo
stream chiamando internamente la open. Dato che il costruttore non può
ritornare un valore, nessuna garanzia sarà data sul successo di questa
inizializzazione. Sarà sempre garatita la validità della classe in se.
Se la open fallisce la classe sarà comunque valida (come se fosse stata
creata con un default constructor). Dopo la creazione si potra'
verificare con le funzioni di query apposite se lo stream e' stato
aperto o meno.
Quindi, in generale, un costruttore NON DEVE mai generare un'eccezione,
salvo che questa non sia parte della costruzione della struttura della
classe. Per esempio se la memoria puntata da this nel costruttore è ROM
o cose simili.
Ma più importante in assoluto è questo: l'impossibilità di aprire uno
stream TCP è un funzionamento previsto dal concetto di stream TCP e
pertanto non deve risultare in una eccezione. Una eccezione è un
avvenimento runtime imprescindibile e incontrollabile in fase di
sviluppo codice. Come ad esempio una divisione per zero o un indice
fuori range. Nel caso specifico di una classe per stream TCP è
accettabile generare una eccezione se vengono passati come parametri di
indirizzo e porta valori non validi (per esempio negativi o fuori range)
salvo che forse sarebbe il caso di usare dei tipi che non lo permettano
(32 bit di indirizzo e 8 di canale, entrambe unsigned). Ma se i valori
in ingresso sono validi e la porta non può essere aperta a causa di
motivi previsti dal protocollo, allora bisogna ritornare un errore e non
generare un'eccezione.
-- 
Posted from 
adsl-21-135.38-151.net24.it
 [151.38.135.21] 


> Quindi, in generale, un costruttore NON DEVE mai generare
un'eccezione,
salvo che questa non sia parte della costruzione della struttura della
classe. Per esempio se la memoria puntata da this nel costruttore è
ROM
o cose simili.
non sono molto d'accordo con questa affermazione: se tu hai un'istanza
di classe che non è stata inizializzata, ovvero il cui costruttore ha
generato un'eccezione, ti ritroverai nell'impossibilità totale di
utilizzare metodi di un oggetto la cui craezione ha avuto qualche
problema. Nell'esempio del socket TCP, impedire la creazione di un
socket su cui non possono essere chiamati metodi come, per esempio,
send() e receive() è un bene. E questo è solo un esempio, ma io quando
realizzo delle classi, cerco sempre di realizzare in modo che la loro
istanziazione o fallisca, e allora quell'oggetto non lo posso proprio
usare, o abbia successo, e i suoi metodi dovrebbero essere il più
possibile esenti da eccezioni o errori (e ribadisco il "il più
possibile"). In questo modo nel blocco try ... catch potrai mettere
l'istanziazione dell'oggetto e la chiamata di tutti i suoi metodi,
come se fosse un unico blocco logico.

come se fosse un unico blocco logico.
Qui rischiamo una flame. Si tratta della vecchia questione di dove deve
essere posto il limite fra errore e eccezione. La teoria e' chiara, poi
tu sei sempre libero di non seguirla. E la teoria dice che una eccezione
e' un avvenimento runtime che non fa parte della normale interfaccia
operativa. Nel caso delle socket una socket puo' avere vari stati, 
compreso l'essere aperta, chiusa, in listen, in handshaking iniziale, in
handshaking finale etc. E' accettabile se tu lanci una eccezione dal 
costruttore di TCPSocket nel caso che sul sistema non esiste uno
stack TCP/IP, purche' esista una funzione (magari statica) che ti 
permette di verificare a priori questa eventualita'. Ma non che la lanci
se non riesci ad aprire la connessione. Almeno secondo la teoria.


generare un'eccezione.
Sono abbastanza d'accordo con quanto dici; ma cosa e' un errore
gestibile e cosa non lo e' dipende secondo me dal contesto.
Il non riuscire ad aprire un file il cui nome e' stato chiesto
all'utente o il non riuscire a stabilire una connessione TCP via
internet sono effettivamente disturbi che in nessun caso
dovrebbero essere cosiderati "eccezionali".
Ma se la connessione TCP e' fra due schede controllo numerico
sulla stessa macchina o fra due processi che devono coordinarsi
sullo stesso calcolatore oppure se il file che non si riesce
ad aprire contiene i dati di configurazione dell'applicazione
allora non ci vedrei nulla di male in una exception... certe cose
non possono andare male (o meglio non c'e' nessun motivo per
cui possano andare male in contesti non eccezionali).
In questi casi inoltre spesso se le cose vanno male non c'e'
molto altro su cui si possa fare affidamento per tentare di
gestire la situazione a parte il mettersi a urlare e bloccare
tutto il bloccabile per evitare danni peggiori.
Quello che intendo dire e' che anche a volte anche se il TCP
ritiene l'errore gestibile (come lo ritiene fopen in lettura
se il file non esiste), per la classe di comunicazione
specifica potrebbe essere una condizione non prevista da cui
ha senso uscire solamente in modo molto brutale.
Andrea
--
Andrea Griffini, Programmer
http://www.netservers.com/~agriff

 se non riesci ad aprire la connessione. Almeno secondo la teoria.
Secondo la "tua" teoria. La teoria dice anche che non esistono modelli
assoluti, ma solo modelli dipendenti dallo scopo per cui vengono creati.
Se uno avviluppa un socket in una classe di supporto e' piu' che
ragionevole che sposti il livello di astrazione dove vuole, ad esempio
anche secondo l'ipotesi "se un TCPSocket esiste, e' aperto". Stara' a
lui gestire correttamente sia creazione che apertura nel costruttore e
segnalare eventuali errori con opportune eccezioni. Mi pare che l'unico
aspetto importante sia mantenere coerenza nel livello di astrazione
prescelto, ad esempio garantendo nel costruttore la gestione di tutti i
casi diversi da "creato e aperto" e nel distruttore solo la sequenza
"chiudi - distruggi".
Ciao,
Nicola

 Qui rischiamo una flame. Si tratta della vecchia questione di dove
deve
essere posto il limite fra errore e eccezione. La teoria e' chiara,
poi
tu sei sempre libero di non seguirla. E la teoria dice che una
eccezione
e' un avvenimento runtime che non fa parte della normale interfaccia
operativa. Nel caso delle socket una socket puo' avere vari stati,
compreso l'essere aperta, chiusa, in listen, in handshaking iniziale,
in
handshaking finale etc. E' accettabile se tu lanci una eccezione dal
costruttore di TCPSocket nel caso che sul sistema non esiste uno
stack TCP/IP, purche' esista una funzione (magari statica) che ti
permette di verificare a priori questa eventualita'. Ma non che la
lanci
se non riesci ad aprire la connessione. Almeno secondo la teoria.
non credo ci sia una teoria che mi dica dove devo utilizzare i
costruttori e dove usare i valori di ritorno x indicare un errore in
questo caso specifico. Io ho realizzato una classe socket TCP e l'ho
realizzata in modo che generi un'eccezione se fallisce la connessione
alla porta dell'indirizzo specificato (in fase di istanziazione), e
questo perchè secondo me un socket che non riesce a collegarsi è un
oggetto inutile.
E' anche vero però che la classe che avevo realizzato io poteva essere
soltanto aperta. Comunque, non volevo assolutamente scatenare flame