View Full Version : Livello di programmazione con vari linguaggi, allocazione dinamica della memoria
^TiGeRShArK^
06-02-2006, 16:51
Emh, ma che stai dicendo?!?!? :rolleyes:
fidati è così....
puoi ridimensionare una collection(ArrayList, Vector, ecc.. ecc...), ma un array nasce a grandezza fissa..
puoi solo riallocarlo creandone un altro con la nuova dimensione...
no no, il codice dice che "byteArray" viene ogni volta re-istanziato(allocato):
"byteArray = new byte[len];"
non viene reistanziato! Ragazzi siete sicuri di quello che state di cendo sì?
mi quoto da solo...
non viene reistanziato! Ragazzi siete sicuri di quello che state di cendo sì?
Sarò più preciso. Tecnicamente viene reinstanziato, ma dopo che il metodo termina NON viene eliminato dal garbage collector!!! Si dice che viene ridimensionato...
non viene reistanziato! Ragazzi siete sicuri di quello che state di cendo sì?
No...nel senso che non sono sicuro per Java perchè non ho studiato Java da un punto di vista teorico...ma in tutti i linguaggi che conosco è così... Se lo ridimensionasse secondo me sarebbe un comportamento non lineare del linguaggio, visto che l'operatore new comporta la creazione di una "nuova" istanza, non il ridimensionamento della vecchia...
^TiGeRShArK^
06-02-2006, 16:54
Arrays are fixed-length structures for storing multiple values of the same type.
http://java.about.com/od/beginningjava/l/aa_array.htm
^TiGeRShArK^
06-02-2006, 16:55
mi quoto da solo...
Sarò più preciso. Tecnicamente viene reinstanziato, ma dopo che il metodo termina NON viene eliminato dal garbage collector!!! Si dice che viene ridimensionato...
pe favore..
fai una prova con la modifica che ti ho suggerito e dimmi ke succede ;)
byteArray = readFileContents(fileName, byteArray);
Non ne sono affatto convinto:
if (byteArray == null || byteArray.length < len)
byteArray = new byte[len];
Magari non sono molto esperto di Java (e questo è vero), ma mi sembra che questo codice, nel caso in cui la lunghezza del buffer non sia sufficiente, allochi un nuovo buffer della lunghezza necessaria e si perda il riferimento a quello vecchio...
Mi sembra un comportamento classico per l'intervento del GC... Se poi mi dici che il problema è byteArray che viene dichiarato come membro della classe...allora mi sembra più un problema di design...ma non è sicuramente un memory leak, in quanto la memoria che rimane allocata ha pur sempre un riferimento... Un memory leak per definizione è irrecuperabile da codice...quindi è un "pezzo" di memora non più raggiungibile dal programma, ma lasciata allocata... Ed in questo caso non lo è...
Nono questo è un tipico caso di memory leak. La memoria è ancora recuperabile, ma rimane inutilmente allocata fino a quando non distruggo la classe (che potrebbe essere distrutta anche alla fine dell'intero programma...) E' uno dei tipi di memory leak, chiamato (per come lo anno insegnato a me) object loitering.
Nono questo è un tipico caso di memory leak. La memoria è ancora recuperabile, ma rimane inutilmente allocata fino a quando non distruggo la classe (che potrebbe essere distrutta anche alla fine dell'intero programma...) E' uno dei tipi di memory leak, chiamato (per come lo anno insegnato a me) object loitering.
Sinceramente fatico a considerarlo un memory leak in senso stretto...ma anche se lo fosse sarebbe impossibile recuperarlo con qualsiasi tecnica...
pe favore..
fai una prova con la modifica che ti ho suggerito e dimmi ke succede ;)
byteArray = readFileContents(fileName, byteArray);
Sinceramente credo che con questo non possa cambiare niente...
^TiGeRShArK^
06-02-2006, 16:58
Nono questo è un tipico caso di memory leak. La memoria è ancora recuperabile, ma rimane inutilmente allocata fino a quando non distruggo la classe (che potrebbe essere distrutta anche alla fine dell'intero programma...) E' uno dei tipi di memory leak, chiamato (per come lo anno insegnato a me) object loitering.
ma se fai la modifica ke ti ho suggerito io e allochi il nuovo array nel metodo dovresti risolvere ogni problema ad okkio...
prova.. non ti costa niente .... e togli la curiostià a tutti noi :D
@TigerShark
Beh certo che riarrangiando il codice puoi evitare il leak ;)
Ah, ma davvero non hai mai ridimensionato un array???????
^TiGeRShArK^
06-02-2006, 16:59
Sinceramente credo che con questo non possa cambiare niente...
perkè?
allocando il nuovo array all'interno del metodo e poi restituendo l'indirizzo di memoria del nuovo array il vekkio array dovrebbe andare perduto alla distruzione del metodo... o no? :mbe:
Hi visto che l'esempio è tratto da qui: http://www-128.ibm.com/developerworks/java/library/j-jtp01246.html
Vediamo se ora sei più contento :D Prova questo:
public class LeakyChecksum {
private byte[] byteArray;
public synchronized int getFileChecksum(String fileName) {
int len = getFileSize(fileName);
if (byteArray == null || byteArray.length < len)
byteArray = new byte[len];
readFileContents(fileName, byteArray);
// Calcola il checksum e ritorna (omesso...)
}
}
Prova pure con Java 1.5 ad usare questa classe, guardando lo stato della memoria con un profiler. Vedrai che, fino a quando non la distruggi, il memory leak c'è eccome, ed il GC non ci fa nulla se non prendi i dovuti accorgimenti. C'è un modo per correggerla ovviamente ;)
Non vorrei dire una bestialata. Ma in questo caso non basta mettere un
byteArray = null; una volta terminata il calcolo? In questo modo si perde l'unico riferimento alla zona di memoria e il gc puo cancellarla.
ciao ;)
Arrays are fixed-length structures for storing multiple values of the same type.
http://java.about.com/od/beginningjava/l/aa_array.htm
Leggilo meglio e tutto... Poi vai a guardare una trattazione più ampia sugli array, fixed-length non è proprio esatto...
MenageZero
06-02-2006, 17:01
appunto con la funzione ke ho rsicritto prima si dovrebbe evitare questo problema...
byteArray = readFileContents(fileName, byteArray);
secondo me readFileContents è ininfluente:
fermo restando che non ne conosciamo il codice, sembra che non facia altro che riempire l'array di vo0lta in volta referenziato da byteArray...
scondo me il punto è solo "byteArray = new byte[len];" (unitamente al fatto che byteArray è var di istanza), perché noi riteniamo che ogni volta venga allocato un nuovo array, mentre fidel che lo stesso array ogni volta venga aumentato di lunghezza (ma mai diminuito) se necessario.
^TiGeRShArK^
06-02-2006, 17:02
@TigerShark
Beh certo che riarrangiando il codice puoi evitare il leak ;)
Ah, ma davvero non hai mai ridimensionato un array???????
non lo puoi ridimensionare..
Puoi solo allocare un nuovo array della dimensione nuova perdendo il riferimento al vecchio....
Quello che dici tu lo puoi fare con arraylist, vector, e tutti gli oggetti di tipo collection.
gli Array in java sono infatti per definizione strutture a lunghezza fissa....
An array is a structure that holds multiple values of the same type. The length of an array is established when the array is created. After creation, an array is a fixed-length structure.
va meglio preso dal sito ufficiale della sun? ;)
http://java.sun.com/docs/books/tutorial/java/data/arrays.html
^TiGeRShArK^
06-02-2006, 17:03
Non vorrei dire una bestialata. Ma in questo caso non basta mettere un
byteArray = null; una volta terminata il calcolo? In questo modo si perde l'unico riferimento alla zona di memoria e il gc puo cancellarla.
ciao ;)
ovvio.. ma mi pare piu' logico spostare la new all'interno del metodo cosi viene deallocato automaticamente il vecchio all'uscita del metodo senza porlo a null esplicitamente ;)
Hi visto che l'esempio è tratto da qui: http://www-128.ibm.com/developerworks/java/library/j-jtp01246.html
Ahahah visto! Queste cose le ho proprio studiate dai vari whitepaper della ibm :D
^TiGeRShArK^
06-02-2006, 17:04
Leggilo meglio e tutto... Poi vai a guardare una trattazione più ampia sugli array, fixed-length non è proprio esatto...
ma come non è proprio esatto??? :mbe:
diglielo a quelli della sun allora che hanno sbagliato la descrizione nel loro sito ufficiale :asd:
kakkio.. te lo stiamo dicendo in tre...
ti ho postato un link...
ti ho postato il link ufficiale della sun e ancora insisti che puoi variare la dimensione di un array dopo averlo allocato??? :mbe:
MenageZero
06-02-2006, 17:05
Non vorrei dire una bestialata. Ma in questo caso non basta mettere un
byteArray = null; una volta terminata il calcolo? In questo modo si perde l'unico riferimento alla zona di memoria e il gc puo cancellarla.
ciao ;)
si se si ritiene che il problema sia che l'ultimo Array istanziato "campi" almeno fino quando "campa" l'intero oggetto LeakyChekSum, ma non sembrava essere questo il punto e cmq allora semplicemente byteArray lo dichiari nel metodo, non come var di istanza
perkè?
allocando il nuovo array all'interno del metodo e poi restituendo l'indirizzo di memoria del nuovo array il vekkio array dovrebbe andare perduto alla distruzione del metodo... o no? :mbe:
Viene perduto anche così...infatti c'è scritto in quel link che questo metodo mette "pressione" al GC... Quindi il Garbage Collector interviene sul vecchio buffer... Il problema è il ciclo vita di byteArray...che è maggiore del suo arco di utilizzo... Ma ripeto...a me più che leak mi sembra un designa errato...
Piccola pausa per festeggiare il mio compleanno ... :p
Per cortesia risparmiami questi patetici esercizi di retorica.
Non è retorica, sono dei libri :p
Tu li hai letti tutti questi libri? Si parla dell'argomento di cui stiamo discutendo? In quali termini? E si parla di questo in tutti i libri o solo in alcuni? Quali? Quali argomentazioni vengono portate a sostegno delle loro tesi (e quali sarebbero le loro tesi?). Se le argomentazioni sono le stesse che hai portato tu, credo sia meglio non buttare i soldi ;)
Certo che li ho letti.
Nessun libro fortunatamente viene pubblicato per parlare di queste cose. I primi libri che ti ho dato, in realtà, non sono libri. Sono dispense pubblicate dal Servizio Editoriale dell'Università di Pisa e sono considerate dei capisaldi dell'informatica teorica. Diciamo che trattano le basi da cui ogni linguaggio formale ha origine. Dovrebbero metterli in pubblicazione da qualche editore serio, visto che io li considero delle bibbie in merito. Dopo averli letti cambia il modo di considerare un linguaggio di programmazione. Ti da un'ottica piu' formale all'argomento. Non è tanto facile trovare simile materiale in libri commerciali, visto che è roba davvero specializzata. Per quanto riguarda il dragon book, basta studiarlo per capire da soli (senza ulteriori libri) quando un linguaggio è di alto e basso livello. Abbiamo detto che il concetto di "medio" è puramente formale e non si considera in genere nella classificazione. I puntatori esistono anche in Pascal. Secondo alcuni ragionamenti che si sono fatti, anche Pascal allora dovrebbe essere di medio/basso livello? ;) Basta contare il numero di parole riservate per dare una stima approssimativa.
P.S.
Visto che pur non sapendo a quali progetti partecipo io dici che "scrivo software banale", mi piacerebbe molto conoscere cosa hai sviluppato TU.
Poi metteremo a confronto le due cose e vedremo chi si farà quattro risate ;)
Io non ho detto che scrivi software banale, ho detto che chiunque partecipi in progetti non banali si rende conto che un bug (anche quelli piu' comuni) non dipendono esclusivamente dall' "attenzione", "cura del codice", "progettazione dell'architettura", tutte cose che tu invece hai elencato come "metodi" per eliminare simili bug. Il livello di attenzione, forte o debole che ognuno di noi ha, rimane "umano". Vista l'impossibilità di scrivere codice complesso senza introdurre bug comuni, è nata l'ingegneria del software. Disciplina che cerca di dare un metodo al processo. E nonostante ciò, non ha eliminato il problema. Da cui i libri che ti ho consigliato di leggere. Ti fanno rendere conto che magari esiste una complessità del software che, da come parli, evidentemente sembri ignorare. Tutto qui. E' inutile sfidarmi sul piano personale. Come non ti conosco io non mi conosci tu. Da dove proviene tutta questa certezza di "vincere"? ;)
Posso scrivere una funzione completamente "bug free". Tuttavia il ruolo di una funzione va considerato anche sul piano semantico in relazione al codice complessivo. Quella funzione "bug free" potrebbe diventare completamente priva di senso in seguito a una modifica da un'altra parte del codice. Moltiplica il tutto per milioni di righe, strutture dati non banali che interagiscono fra loro, funzioni che si basano sul contenuto di una struttura che al minimo cambiamento diventano inconsistenti e ti rendi conto che il discorso "dell'attenzione" che facevi tu si continua ad applicare solo a software banale.
Il cervello umano riesce a gestire (male) un massimo di 3 cose contemporaneamente. E' la biologia che lo dice, non serve neanche considerare l'informatica.
^TiGeRShArK^
06-02-2006, 17:08
Viene perduto anche così...infatti c'è scritto in quel link che questo metodo mette "pressione" al GC... Quindi il Garbage Collector interviene sul vecchio buffer... Il problema è il ciclo vita di byteArray...che è maggiore del suo arco di utilizzo... Ma ripeto...a me più che leak mi sembra un designa errato...
ma infatti E' un desing errato...
questo è proprio il problema del passaggio per riferimento...
facendo la new nel metodo appena chiamato e ricevendo il riferimento al nuovo vettore non si stressa per niente il GC dato che quell'oggetto viene eliminato automaticamente alla morte del metodo...
ripeto... MAI effettuare passaggi per riferimento... porta sempre a errori di questo tipo...
^TiGeRShArK^
06-02-2006, 17:09
Piccola pausa per festeggiare il mio compleanno ... :p
AUGURI! :D
Comunque mjordan... quei libri (dai titoli) sembrerebbero abbastanza "basilari" (tranne "Ingegneria del software", materia tra l'altro trattata nel corso di Ingegneria Informatica) e mi sembrerebbero più adatti ad un pubblico come te :)
Se li leggi ti accorgi che non sono proprio elementari come li consideri... Come fai a stipulare un verdetto dai soli titoli... Un qualcosa prima di essere giudicato va letto. Il Fowler che ti ho dato non è proprio banale. Ti fa rendere conto che UML non è soltanto un class diagram. Il dragon Book all'unanimità è pure considerato un testo "difficile", non adatto ai principianti e l'ho preso proprio perchè ho visto un esperto come te. ;)
Leggili.
Tra l'altro alcuni di quelli sono poco inerenti all'argomento di discussione :)
L'argomento trattato non è altro che una discussione che si basa su opinioni che invece hanno fondamento in quelle discipline. Da cui i libri che ti ho citato. Prima di discutere di qualcosa ci vuole fondamento. :read:
Non vorrei dire una bestialata. Ma in questo caso non basta mettere un
byteArray = null; una volta terminata il calcolo? In questo modo si perde l'unico riferimento alla zona di memoria e il gc puo cancellarla.
Sì, ma l'intenzione di chi l'ha scritto (si legge sempre nel link) è cachare l'array per ottimizzarne l'accesso (ovviamente fino a quando non necessitiamo di una dimensione maggiore)...
http://www-128.ibm.com/developerworks/java/library/j-jtp01246.html
UML non mi sembra particolarmente ostico.
UML non è soltanto costituito da Class diagram. UML può diventare terrificante. Certo non è difficile da imparare, ma provare a implementare qualcosa che risci a concepire in UML è un'altro "esercizio" per capire dove può arrivare la complessità del software. E che quindi il livello di "attenzione" non c'entra ancora nulla.
ma come non è proprio esatto??? :mbe:
diglielo a quelli della sun allora che hanno sbagliato la descrizione nel loro sito ufficiale :asd:
kakkio.. te lo stiamo dicendo in tre...
ti ho postato un link...
ti ho postato il link ufficiale della sun e ancora insisti che puoi variare la dimensione di un array dopo averlo allocato??? :mbe:
Hai ragione scusami, sono stato molto poco chiaro. Io (ma non solo io) lo chiamo ridimensionamento, e mi spiego meglio.
Nella funzione che ho scritto, quando la lunghezza del buffer non basta più, ho bisogno di crearne un altro più grande che andrà bene. Ora, se reinstanzio la stessa variabile, la vecchia memoria viene distrutta (perdendo tutto il contenuto) e viene riallocato con la nuova dimensione (ecco il ridimensionamento. Nell'esempio il problema sta nel fatto che, una volta riallocato, il buffer NON viene cancellato dal GC perchè il suo reference NON è nel metodo ma nella classe!
ripeto... MAI effettuare passaggi per riferimento... porta sempre a errori di questo tipo...
Ma dov'era il apssaggio epr riferimento prima :confused:
comunque il C# è un linguaggio fantastico! peccato che lo ha acquistato MS :rolleyes:
Il C# è uno standard ECMA. Quindi non è poi tanto diverso dal C o dal C++. Anzi, lo puoi considerare addirittura piu' liberale di Java. Peccato che non si possa dire lo stesso per le API chiaramente.
In C/C++ non ho mai scritto da solo programmi lunghi migliaia di righe, ma in altri linguaggi in cui "l'errore è sempre dietro l'angolo" si (come per il PHP le varie "sql injection", "directory transversal", "cross scripting" etc.) e sono abbastanza sicuro sul fatto che non contenessero falle di sicurezza, poichè quando sviluppo presto la massimo cura ed attenzione agli aspetti più svariati (efficienza, sicurezza, pulizia del codice), il che lascia davvero poco spazio ad errori di questo genere (ho detto "abbastanza" perchè certamente qualcuno può essermi sfuggito... quale essere umano sono ben lontano dalla divina perfezione, ma certamente mi considero notevolente più "attento" rispetto ad alcuni sviluppatori che ho avuto l'occasione di conoscere nella mia "giovane vita"). Come già detto (di nuovo) *nessuno* (spero) afferma che vi sia un programmatore che non commette alcun errore, ma sicuramente c'è chi ne commette di più e chi ne commette meno. :) Mi sembra un discorso ragionevole.
Come volevasi dimostrare ;)
La "sicurezza" che hai proviene da due elementi di giudizio:
1) Sicurezza che in fondo non lo è.
2) Sicurezza certa dovuta a estrema semplicità del codice trattato.
Io credo che la tua sia un mix di entrambi i punti. 2000 righe di codice C/C++ inolte non sono proprio la stessa cosa che 2000 righe di codice PHP, vista "l'indulgenza sintattica" per cui questo linguaggio è famoso. Lo stesso dicasi per SQL.
mjordan: dai...non alimentiamo la polemica...ormai il discorso si era spostato su altri lidi ;)
mjordan: dai...non alimentiamo la polemica...ormai il discorso si era spostato su altri lidi ;)
Tra l'altro un bel lido per questo thread. Allora ragazzi ci siamo? TigerShark, ti ritrovi sul "ridimensionamento"?
mi sono perso nel thread e non ho più capito chi aveva ragione e chi no :-|
comunque dico la mia:
1) secondo me un linguaggio in cui l'allocazione dinamica della memoria disponga di un sistema di garbage collection (Java e simili insomma :p) permette per definizione al programmatore di strafregarsene di deallocare memoria e di non commettere leaks (è precisamente quello che stiamo facendo noi di Diamond Crush: mai deallocato un oggetto, mai nemmeno richiamato il metodo che si usa in Java per la finalizzazione; forse giusto in una classe, per chiudere le librerie sonore, ma in caso quello sarebbe un resource leak, non proprio un memory leak)
No? Leggi il link che ho postato dietro :read:
2) la definizione del C come linguaggio di "medio livello" mi sembra buona, anche se (suppongo) inventata sul momento; faccio un esempio pratico per spiegare la mia visione e come mai ritengo che sia una definizione molto adatta:
No no affatto. In molti cercano di classificare il medio livello, invece, anche se non è mai entrato di fatto come "voce di catalogazione".
la motivazione mi sembra più che evidente no? non è solo un fatto di estetica sintattica e di parentesi graffe come scritto da mjordan: il C e il C++ si trovano a metà tra il bash e l'assembly perché permettono un controllo su diversi aspetti funzionali decisamente superiore a quello permesso dal bash e ma magari inferiore a quello dell'assembly (se escludiamo il caso in cui, tramite l'uso di estensioni sintattiche specifiche di un compilatore, un sorgente C/C++ contenga degli stub scritti in assembly).
Quindi Pascal che consente di manipolare i puntatori e di basso livello. . .
Esempio pratico: proprio la memoria dinamica e i puntatori. con linguaggi di medio livello (come C, C++, Delphi, e altri) è possibile allocare e deallocare a piacere, è possibile creare dangling pointers facendo addizioni, castando a int, maneggiando a piacere e ri-castando a puntatore, eccetera eccetera; col bash invece non posso fare alcunché di tutto ciò; o meglio, da quel poco che conosco di questo linguaggio sarebbe possibile banalmente tramite un altro programma (scritto magari in C o C++) ed eseguito da una shell bash, ma così ovviamente si rende necessario l'uso dell'altro linguaggio e quindi non possiamo considerarla tutta una potenzialità del bash. :)
Appunto... Delphi è di medio livello....
se mi obiettate che il bash non va bene come esempio di linguaggio di alto livello allora vi faccio immediatamente un altro esempio che secondo me (giudizio totalmente empirico) è ad un livello sempre alto, ma un po' più "basso" rispetto al bash: il Java. di nuovo, con Java non posso certo fare tanti bei giochetti coi puntatori che invece in C, C++ e Delphi posso fare tranquillamente (ed è proprio questa una delle caratteristiche migliori di Java: in Java praticamente i buffer overflow e i buffer overrun non esistono!).
Ok. Ma "il bash" non è un linguaggio. BASH significa Bourne Again SHell ed è una shell. E' semplicemente uno scripting language che è diverso da un linguaggio di programmazione.
^TiGeRShArK^
06-02-2006, 17:25
Ma dov'era il apssaggio epr riferimento prima :confused:
riempiva l'array passandogli per valore la copia del riferimento della variabile di classe contenente l'array a quanto ho capito.....
infatti quella variabile era di tipo void...
in realtà avrebbe potuto semplicemente accedervi dal metodo ora ke ci penso senza passargli l'array poichè lo vedeva come variabile di classe se ricordo bene il codice...
non lo puoi ridimensionare..
Puoi solo allocare un nuovo array della dimensione nuova perdendo il riferimento al vecchio....
Quello che dici tu lo puoi fare con arraylist, vector, e tutti gli oggetti di tipo collection.
gli Array in java sono infatti per definizione strutture a lunghezza fissa....
Per definizione sì, ma a runtime puoi renderli array dinamici, con il seguente semplice metodo:
int x[] = new int [20];
...
x = new int [40];
Ovviamente perdi il contenuto di x perchè x viene distrutto e riallocato.
MenageZero
06-02-2006, 17:26
Hai ragione scusami, sono stato molto poco chiaro. Io (ma non solo io) lo chiamo ridimensionamento, e mi spiego meglio.
Nella funzione che ho scritto, quando la lunghezza del buffer non basta più, ho bisogno di crearne un altro più grande che andrà bene. Ora, se reinstanzio la stessa variabile, la vecchia memoria viene distrutta (perdendo tutto il contenuto) e viene riallocato con la nuova dimensione (ecco il ridimensionamento. Nell'esempio il problema sta nel fatto che, una volta riallocato, il buffer NON viene cancellato dal GC perchè il suo reference NON è nel metodo ma nella classe!
beh magari il gc non interviene sul "vecchio" array contestualmente alla nuova allocazione(dato che anch'essa è nel metodo) ma potrà farlo in qualunque momento futuro quando riterrà opportuno (al limite non mentre è in secuizione quel metodo se tu dici che c'è questo vincolo) se necessario anche prima che venga dereferenziato l'oggetto LeakyChekSum...
quindi non ho capito come nascerebbe un vero mem leaky, cioè cosa renderà inattaccabili dal gc le vecchie istanze di byteArray non più referenziate ?
Ovviamente perdi il contenuto di x perchè x viene distrutto e riallocato.
Nell'esempio che ho fatto però, non viene distrutto...
Sì...viene distrutto... C'è anche scritto nel link...
At the very least, this puts pressure on the garbage collector and requires more frequent collections;
ehm....scusa se torno a ropetermi...
ma come fai a deallocare la memoria in java??? :mbe:
ogni oggetto, come ho già detto prima, non è altro ke un "puntatore" all'heap....
Tu al massimo puoi scrivere object = null; ma questo non equivale a deallocare la memoria, serve a eleiminare il riferimento in modo ke il GC possa deallocare la memoria.
Ma tu non PUOI deallocare la memoria manualmente, al max puoi lanciare un esecuzione del GC subito dopo aver posto l'oggetto a null, ma questa è una pratica ke, tranne in casi particolari, è FORTEMENTE sconsigliata, perchè il GC agisce già di suo, se ti metti ad invocarlo troppe volte non farai altro ke peggiorare le prestazioni del tuo programma dato ke il GC dovrà girare piu' volte e occuperà risorse sulla tua makkina....
Se ti riferisci al metodo finalize(), neanch'esso ti da la certezza di far entrare in azione il Garbage Collector. Esso in realtà stabilisce soltanto che il Garbage Collector debba tener conto di ciò forzatamente al momento della sua esecuzione, ma non è un richiamo "esplicito" di far entrare in funzione il Garbage Collector.
Il metodo finalize() infatti non fa entrare in azione il Garbage Collector come si pensa.
Una cosa importante da sapere è che finalize() viene chiamato solo PRIMA di essere eseguito il garbage collector e non quando un'oggetto esce dall'ambito. Quindi non c'è un modo esatto per sapere quando finalize() venga chiamato. E' una precisazione importante. finalize() non dev'essere considerato come un distruttore di classe, insomma.
Se non ti riferivi a finalize(), chiedo venia allora.... :p
beh magari il gc non interviene sul "vecchio" array contestualmente alla nuova allocazione(dato che anch'essa è nel metodo) ma potrà farlo in qualunque momento futuro quando riterrà opportuno (al limite non mentre è in secuizione quel metodo se tu dici che c'è questo vincolo) se necessario anche prima che venga dereferenziato l'oggetto LeakyChekSum...
quindi non ho capito come nascerebbe un vero mem leaky, cioè cosa renderà inattaccabili dal gc le vecchie istanze di byteArray non più referenziate ?
C'è una incomprensione di fondo. Il problema risiede nel fatto che, ad esempio:
1) istanzio 'byteArray' da 10 mega e la uso
2) ho bisogno di un buffer più grosso: reistanzio byteArray da 20 Mb. i 10 mega di prima vengono subito rimossi, e ne vengono riallocati 20.
3) il GC rimuoverà i 20 mega solo quando vado a cancellare la classe!
Non è un memory leak classico, viene chiamato memory leak di tipo "object loitering", quel buffer viene tranquillamente eliminato quando rimuovo l'intera classe, ma nel frattempo sta lì a rubare inutilmente memoria.
quindi non ho capito come nascerebbe un vero mem leaky, cioè cosa renderà inattaccabili dal gc le vecchie istanze di byteArray non più referenziate ?
Da quello che ho capito questo memory leak...definito "object loitering"...cotinua a tenere allocata (e non raggiungibile dal GC, perchè sempre referenziata) l'istanza corrente del vettore...anche quando alla classe non serve più calcolare check sum...e rimarrà occupata fino a quando la classe stessa non verrà distrutta...
Secondo me non è definibile memory leak... E' come se io in C mi tenessi in una variabile globale un puntatore ad un vettore ottenuto con realloc...e poi quando non mi serve più non chiamo volutamente la free... A me sembra più un design non corretto...
Sì...viene distrutto... C'è anche scritto nel link...
At the very least, this puts pressure on the garbage collector and requires more frequent collections;
Certo ;) Come detto prima, ho studiato queste cose proprio da quei whitepapers.
Certo ;) Come detto prima, ho studiato queste cose proprio da quei whitepapers.
Cercavo solo di far capire agli altri la situazione...cioè qui si è cercato di fare un'ottimizzazione...rendendo sempre disponibile in cache il vettore (ogni nuova istanza si intende)... L'errore secondo me è qui: cercare di ottimizzare...
Se si cerca di ottimizzare allora bisogna ottimizzare anche LeakyCheckSum...in modo da rendere il suo ciclo di vita il più corto possibile...
Alla base c'è comunque un errato design e non un errore di coding...come per la maggior parte dei memory leak...
MenageZero
06-02-2006, 17:38
Per definizione sì, ma a runtime puoi renderli array dinamici, con il seguente semplice metodo:
int x[] = new int [20];
...
x = new int [40];
Ovviamente perdi il contenuto di x perchè x viene distrutto e riallocato.
ma lo dici anche tu!
ripeto: "...riallocato"
anche se quando viene distrutto (dal gc) non lo sai a priori, la mem non più usata dal nuovo array, può essere "preda" del gc! e il leak ?(ovviamente riferito al famoso esempio dove il punto è lo stesso)
Da quello che ho capito questo memory leak...definito "object loitering"...cotinua a tenere allocata (e non raggiungibile dal GC, perchè sempre referinziata) l'istanza corrente del vettore...anche quando alla classe non serve più calcolare check sum...e rimarrà occupata fino a quando la classe stessa non verrà distrutta...
Benissimo :D
Secondo me non è definibile memory leak... E' come se io in C mi tenessi in una variabile globale un puntatore ad un vettore ottenuto con realloc...e poi quando non mi serve più mi scordo di chiamare la free... A me sembra più un design non corretto...
Non so cosa intendi per design non corretto, però può fare comodo, a livello di design, avere un buffer dichiarato non nel metodo (magari quando deve essere usato da più metodi e non vuoi che venga continuamente allocato e liberato). Poi però bisogna stare attenti! Questo era per far vedere che il GC non ti salva sempre dai problemi di memoria. Questo non è un memory leak "in senso stretto" della definizione, è solo di un tipo diverso, ma ti dà sempre grossi problemi. La differenza che ci vedo da un memry leak standard è che comunque, all'interno dell'applicazione, la memoria istanziata da quella classe è comunque raggiungibile (non a caso viene distrutta quando distruggo l'oggetto).
ma lo dici anche tu!
ripeto: "...riallocato"
anche se quando viene distrutto (dal gc) non lo sai a priori, la mem non più usata dal nuovo array, può essere "preda" del gc! e il leak ?(ovviamente riferito al famoso esempio dove il punto è lo stesso)
Mi pare di averlo già detto... ok ripeto ;)
Non è un leak "nel senso stretto" del termine, perchè comunque quella memoria prima o poi sarà raggiungibile dal GC (in particolare quando distruggo la classe), ma fino a quando quell'oggetto è istanziato, quel buffer rimane lì rubando inutilmente memoria (anche molta memoria...). E' un particolare tipo di memory leak, non meno pericoloso del leak "per definizione", chiamato "memory leak di tipo object loitering".
Non so cosa intendi per design non corretto, però può fare comodo, a livello di design, avere un buffer dichiarato non nel metodo (magari quando deve essere usato da più metodi e non vuoi che venga continuamente allocato e liberato).
Design nel senso di "progettazione" della classe... E' chiaro che se serve a più metodi è utile...ma se serve ad un solo metodo e lo si fa per rendere l'applicazione l'0.5% (ho tirato a caso) più veloce perchè resta in cache...allora si parte da un presupposto errato...
Se si cerca di ottimizzare allora bisogna ottimizzare anche LeakyCheckSum...in modo da rendere il suo ciclo di vita il più corto possibile...
Alla base c'è comunque un errato design e non un errore di coding...come per la maggior parte dei memory leak...
Straquoto. I memory leak (e simili) sono fondamentalmente "errori" (normalmente poco visibili), di programmazione, ed il povero GC poco ci può fare...
Design nel senso di "progettazione" della classe... E' chiaro che se serve a più metodi è utile...ma se serve ad un solo metodo e lo si fa per rendere l'applicazione l'0.5% (ho tirato a caso) più veloce perchè resta in cache...allora si parte da un presupposto errato...
Capito ;) ...e sono d'accordo con te.
MenageZero
06-02-2006, 17:51
Da quello che ho capito questo memory leak...definito "object loitering"...cotinua a tenere allocata (e non raggiungibile dal GC, perchè sempre referenziata) l'istanza corrente del vettore...anche quando alla classe non serve più calcolare check sum...e rimarrà occupata fino a quando la classe stessa non verrà distrutta...
ma cavolo! ovvio! è semplicemente conseguenza della definizione di var di Istanza di una classe e del fatto che byteArray viene dichiarato come tale !
chiaro che l'istanza correntefinché è referenziata nessuno l'ammazza, e ovviamente se è var di istanza è referenziata(e intoccabile) finché esiste l'oggetto che la include!
e di che problema di leak che sfugge al gc parliamo allora ? :)
basta decidere se preferisco avere l'array "cached" ma allocato anche quando non mi serve o il contrario e in base a ciò dichiaralo nel metodo o fuori
Secondo me non è definibile memory leak... E' come se io in C mi tenessi in una variabile globale un puntatore ad un vettore ottenuto con realloc...e poi quando non mi serve più mi scordo di chiamare la free... A me sembra più un design non corretto...
appunto !
Intendevo il contraro: in questo caso c'è un errore di design...ma classicamente sono gli errori di coding a provocare memory leak...almeno quando chi programma è padrone dello strumento...
e di che problema di leak che sfugge al gc parliamo allora ? :)
Appunto del fatto che quel buffer può crescere arbitrariamente e restare allocato anche per molto tempo a partire da quando non lo utilizziamo più...guarda qui: http://www-128.ibm.com/developerworks/java/library/j-jtp01246.html
Sì...viene distrutto... C'è anche scritto nel link...
At the very least, this puts pressure on the garbage collector and requires more frequent collections;
Sì mi riferivo al nuovo buffer reistanziato, non a quello vecchio, quello lo perdi subito ovviamente ;)
ma non sembrava essere la persistenza dell' istanza corrente il "cruccio" di fidel... boh... :confused:
Nono è proprio quello il problema, non mi riferivo alla reallocazione! Ovviamente quando rialloco, il vecchio buffer viene subito collezionato, ma quello nuovo poi rimane fino a quando la classe non viene distrutta ;) E ci rimane inutilmente. Cmq ho poi scritto abbondantemente, vedi i post precedenti :D
^TiGeRShArK^
06-02-2006, 18:01
Sì mi riferivo al nuovo buffer reistanziato, non a quello vecchio, quello lo perdi subito ovviamente ;)
ah ora ho capito....
ma mi pare normale ke quello nuovo rimanga allocato..
se l'hai allocato come variabile di classe ti dovrà pur servire a qualcosa...
altrimenti lo dichiari SOLO nel metodo che lo uttilizza come è buona prassi....
quindi non vedo dove sia il memory leak qui.... è stata una scelta del programmatore..... se è una scelta sbagliata ok... ma il GC ke ne può sapere ke il programmatore è un kazzone! :D
[OT] Devo scappare, ci risentiamo dopo le 20 ;) Mi pare che ora sia tutto chiaro no? Ciao!
ah ora ho capito....
ma mi pare normale ke quello nuovo rimanga allocato..
se l'hai allocato come variabile di classe ti dovrà pur servire a qualcosa...
altrimenti lo dichiari SOLO nel metodo che lo uttilizza come è buona prassi....
quindi non vedo dove sia il memory leak qui.... è stata una scelta del programmatore..... se è una scelta sbagliata ok... ma il GC ke ne può sapere ke il programmatore è un kazzone! :D
Appunto ;) rileggi i post miei e di cionci di poco fa :D I leak sono sempre (a meno di problemi nelle libreria o in questo caso della JVM) "colpa" del programmatore. Guarda che in questo caso però, se hai bisogno di un buffer "cached", non è proprio così banale...
^TiGeRShArK^
06-02-2006, 18:04
Appunto ;) rileggi i post miei e di cionci di poco fa :D
si si ho letto.. apposta ho scritto ke ho capito...
all'inizio credevo ke il GC non facesse in tempo a deallocare il VECCHIO oggetto perchè esso veniva istanziato troppe volte.....se fosse accaduto quello sarebbe stato un memory leak imho...
mentre così facendo non c'è nessun memory leak... la VM sta semplicemente seguendo la volontà del programmatore.. ne' + ne' - ...
si si ho letto.. apposta ho scritto ke ho capito...
all'inizio credevo ke il GC non facesse in tempo a deallocare il VECCHIO oggetto perchè esso veniva istanziato troppe volte.....se fosse accaduto quello sarebbe stato un memory leak imho...
mentre così facendo non c'è nessun memory leak... la VM sta semplicemente seguendo la volontà del programmatore.. ne' + ne' - ...
Non è un memory leak "per definizione" è un tipo differente di memory leak, non meno preoccupante. Semplicemente il GC non ti salva dagli errori più o meno gravi o evidenti che portano a problemi di memoria.
^TiGeRShArK^
06-02-2006, 18:08
Non è un memory leak "per definizione" è un tipo differente di memory leak, non meno preoccupante. Semplicemente il GC non ti salva dagli errori più o meno gravi o evidenti che portano a problemi di memoria.
ke si eviterebbero seguendo le giuste metodologie di programmazione che non per niente predicano sempre di utilizzare solo quando necessario le variabili di classe :sofico:
ke si eviterebbero seguendo le giuste metodologie di programmazione
Sotto questo punto di vista anche gli altri memory leak lo sono ;)
rdefalco
06-02-2006, 18:17
In 8 pagine del thread avevo capito che anche le precedenti allocazioni dell'array fossero parte del "memory leak". Ma non potreste essere più chiari? Solo adesso mi è tutto chiaro...
MenageZero
06-02-2006, 18:21
Nono è proprio quello il problema, non mi riferivo alla reallocazione! Ovviamente quando rialloco, il vecchio buffer viene subito collezionato, ma quello nuovo poi rimane fino a quando la classe non viene distrutta ;) E ci rimane inutilmente. Cmq ho poi scritto abbondantemente, vedi i post precedenti :D
infatti al momento del mio ultimo post non avevo ancora letto alcuni tuoi, pi ho anche editato quella frase...
guarda ora ci intendiamo perfettamente:
fin dall'inizio era chiarissimo anche a me che l'ultima, in ordine di tempo, istanza di quel vettore rimane allocata almeno fino a che è referenziato l'oggetto LeakyCheckSum, essendo dichiarato fuori dal metodo, e che se parliamo di significative quantità di memoria che rimane inusabile per altro è un problema che supera abbondantemente il vantaggio con ogni probabilità poco sensibile dell'avere l'array "cached"...
però potevi focalizzarci subito l'attenzione! :D
hai iniziato con il "ridimensionamento" dello "stesso" array, con il gc() che non risolveva un leak, con memoria percedentementen allocata che non poteva venir liberata e "ci hai lasciato credere" che ti riferissi a memoria spesa in una struttura(sempre stesso vettore sovradimensionato o istanze diverse che fossero) non più referenziata (se non refernziata il gc invece interviene).
***re-edit***
va be', sara che anche io inizialmente ho colto (molto)male le "sfumature" di quello che dicevi ;)
ora il gc non risolve questo "problema" chiaro, ma si tratta di una scelta esplicita e consapevole(se pur errata nella maggior parte di casi concreti) del programmatore, scielta che "sfrutta" la regola, piuttosto sensata direi, che il gc non deallochi oggetti referenziati, per diventare un "leak" se proprio bisogna chiamarlo così...
beh finalmente posso postare questo: :mano:
e per completezza, @cionci: :mano:
mjordan: dai...non alimentiamo la polemica...ormai il discorso si era spostato su altri lidi ;)
Scusa, ho visto dopo. Va bhè chiudo qua, tanto non ho piu' nulla da dire in merito "bug e competenze personali". :D
EDIT: Comunque ho perso il filo con il discorso del leak da Java. Com'è andato a finire? :p
però potevi focalizzarci subito l'attenzione! :D
hai iniziato con il "ridimensionamento" dello "stesso" array, con il gc() che non risolveva un leak, con memoria percedentementen allocata che non poteva venir liberata e "ci hai lasciato credere" che ti riferissi a memoria spesa in una struttura(sempre stesso vettore sovradimensionato o istanze diverse che fossero) non più referenziata (se non refernziata il gc invece interviene)
Ammetto di non avere il dono della sintesi ;) Soprattutto mi spiace che "vi ho lasciato credere" che mi riferissi a memoria spesa in una struttura non più referenziata: pensavo che si capisse subito (l'ho pure detto a più riprese) che ridimensionavo l'array referenziato da byteArray, e che quello rimaneva allocato anche quando non serviva più al metodo (qui il "memory leak" di tipo object loiting), ma che veniva deallocato alla distruzione dell'oggetto (quindi non un memory leak "per definizione"). :D
Penso che l'incomprensione sia nata dal fatto che tutti si aspettavano un memory leak "per definizione", cioè memoria non più raggiungibile dal GC, solo dopo ho capito ed ho precisato che era un memory leak di tipo "object loiting" ;)
edit: poi ad un certo punto mi pare dicevi che l'arrya poteva solo aumentare (invece se allochi una dimesione inferiore a quella precedente, quella che rimane allocata è sempre l'ultima)...
No spe qui hai capito benissimo ed è proprio così in quell'esempio!! Ti riposto il pezzo in questione:
if (byteArray == null || byteArray.length < len)
byteArray = new byte[len];
L'array viene ridimensionato solo se serve che sia più grande, quindi non può far altro che crescere ;)
ora il gc non risolve questo "problema" chiaro, ma si tratta di una scelta esplicita e consapevole(se pur errata nella maggior parte di casi concreti) del programmatore, scielta che "sfrutta" la regola, piuttosto sensata direi, che il gc non deallochi oggetti referenziati, per diventare un "leak" se proprio bisogna chiamarlo così...
Beh ma i memory leaks e simili non sono sempre (a parte problemi di libreria o in questo caso della JVM) degli errori più o meno evidenti del programmatore? Immagina l'esempio in questione in un contesto dove serve un buffer "cache", il tutto tra 100.000 righe di codice ;) Certo, se scrivo un programma di 100 righe e mi faccio sfuggire una cosa del genere sono davvero poco attento!
Il tutto, ricordo, è nato dal fatto che il povero GC non risolve tutti i problemi, ci semplifica la vita ma non corregge i nostri errori, e come detto è dagli errori che nascono memory leaks e simili :(
In 8 pagine del thread avevo capito che anche le precedenti allocazioni dell'array fossero parte del "memory leak". Ma non potreste essere più chiari? Solo adesso mi è tutto chiaro...
Dico la stessa cosa che ho detto a ManageZero:
penso che l'incomprensione sia nata dal fatto che tutti si aspettavano un memory leak "per definizione", cioè memoria non più raggiungibile dal GC, solo dopo ho capito ed ho precisato che era un memory leak di tipo "object loiting" ;)
EDIT: Comunque ho perso il filo con il discorso del leak da Java. Com'è andato a finire? :p
Credo che ora sia chiaro ;)
[OT] A proposito, auguri!
Certo che programmare così in C++ è un po' da matti ;) Ti posso capire con il C in cui c'è una certa "tradizione", ma il C++ anche se ti "offre" comunque questi strumenti, li vedrai messi in opera raramente in un programma serio... be', non è detto: ci sono ambiti in cui maneggiare puntatori "allegramente" è necessario, mi riferisco specialmente alla programmazione di sistema (device drivers o parti del sistema operativo stesso) ma non è neanche detto che tecniche come quelle che ho descritto siano tanto "folli" da usare in programmi "normali": per esempio, mettiamo di aver caricato in memoria il nodo di un B-albero letto da un file; nel file è presumibile che i puntatori ai figli siano realizzati tramite offset dall'inizio del file o degli RVA, mentre in RAM è sicuramente più comodo convertirli tutti in indirizzi virtuali veri e propri; qui non si scappa, devo fare le addizioni :)
e siccome (se la memoria non m'inganna) il compilatore non permette di addizionare due puntatori (che nell'esempio del B-albero sarebbero un indirizzo base e un offset), è necessario prima convertire a interi (possibilmente senza segno) e poi di nuovo a puntatori ;)
MenageZero
06-02-2006, 20:51
Ammetto di non avere il dono della sintesi ;) Soprattutto mi spiace che "vi ho lasciato credere" che mi riferissi a memoria spesa in una struttura non più referenziata: pensavo che si capisse subito (l'ho pure detto a più riprese) che ridimensionavo l'array referenziato da byteArray, e che quello rimaneva allocato anche quando non serviva più al metodo (qui il "memory leak" di tipo object loiting), ma che veniva deallocato alla distruzione dell'oggetto (quindi non un memory leak "per definizione"). :D
Penso che l'incomprensione sia nata dal fatto che tutti si aspettavano un memory leak "per definizione", cioè memoria non più raggiungibile dal GC, solo dopo ho capito ed ho precisato che era un memory leak di tipo "object loiting" ;)
personalmente all'inizio è stata proprio la ricorrenza del verbo "ridimensionare" riferito all'array con i riferimenti a memoria che rimaneva allocata che mi ha portato sulla "falsa pista" ad arrovellarmi su memoria eventualmente non più raggiungibile dal gc e a credere che tu fraintendessi il meccanismo di ri-allocazione etc. etc.
il punto vero del "maledetto coso" che muore non prima dell'oggetto che lo include lo vedevo da subito tanto ovvio che non pensavo fosse quello il problema a cui ti riferivi :D
cmq l'importante alla fine è intendersi :)
No spe qui hai capito benissimo ed è proprio così in quell'esempio!! Ti riposto il pezzo in questione:
if (byteArray == null || byteArray.length < len)
byteArray = new byte[len];
L'array viene ridimensionato solo se serve che sia più grande, quindi non può far altro che crescere ;)
qui auto-impongo 5 min. di vergogna: è indubbiamente come dici tu, il fatto è che nell'ultimo mio post, ormai molto dopo che avevi postato l'ormai famoso esempio, avevo completamente dimenticato la presenza di quell'if mentre scrivevo quella frase... :muro: ...che ora corro ad ri-editare :)
Beh ma i memory leaks e simili non sono sempre (a parte problemi di libreria o in questo caso della JVM) degli errori più o meno evidenti del programmatore? Immagina l'esempio in questione in un contesto dove serve un buffer "cache", il tutto tra 100.000 righe di codice ;) Certo, se scrivo un programma di 100 righe e mi faccio sfuggire una cosa del genere sono davvero poco attento!
Il tutto, ricordo, è nato dal fatto che il povero GC non risolve tutti i problemi, ci semplifica la vita ma non corregge i nostri errori, e come detto è dagli errori che nascono memory leaks e simili :(
certo sempre errori del programmatore sono, ma quello, anche se immaginandolo disperso in 10^n righe di codice in effetti umanamente assume più l'aspetto di una dimenticanza come altre, è in se un po' diverso da ad esempio, scordarsi di liberare una risorsa o della ram con una chiamata esplicita quando sai che lo devi fare come procedura abituale e 100 volte lo fai ed 1 ti dimentichi...
(in quell'esempio se usi la var di classe e metti quell'if nel metodo è perché volevi la pesistenza, a torto o rgaione, di quel buffer, non è che lo dichiari lì con l'intenzione di metterlo a null appena non serve più e poi ti scordi di farlo, allora lo dichiaravi direttamente nel metodo... è un "tu generico", eh :) )
ciao, vado a cenare
ps: @mjordan: mi unisco agli auguri di compleanno!
be', non è detto: ci sono ambiti in cui maneggiare puntatori "allegramente" è necessario, mi riferisco specialmente alla programmazione di sistema (device drivers o parti del sistema operativo stesso)
Certo...infatti quello è solitamente l'ambiente principale del C...
Se parli di 90 % sono d'accordo, se parli di "definitivamente sì" non lo sono più. Parlando nello specifico di Java, volendo fare un discorso "tecnicamente più preciso" come dici tu, puoi leggere questo (http://www-128.ibm.com/developerworks/library/j-leaks/) articolo. Ovvio che i GC riducono i memory leaks, è uno dei motivi per cui sono stati pensati, ma non li eliminano del tutto (magari!). be' ciò che è scritto nel link che mi hai dato è vero ma significa che il leak è causato dal fatto che ancora tengo dei references e ancora ho la possibilità di controllo sugli oggetti non deallocati... in altre parole è un problema di design... la differenza tra come la vedi tu e come la vedo io è piuttosto sottile: io sono abituato a pensare al memory leak vero e proprio quando si perde ogni riferimento ma il blocco di memoria dinamica rimane; in tal caso esso non può più essere liberato se non ovviamente quando il processo viene terminato dal sistema operativo perché a quel punto l'unico software che continua ad avere il controllo di quel blocco è appunto il sistema operativo stesso.
tu invece consideri il memory leak fin da quando inizia a presentarsi il problema di design del reference tenuto inutilmente; punti di vista insomma, se vogliamo vederla come la vedi tu allora ti do perfettamente ragione.
Su Java sei più ferrato, su bash molto meno a quanto pare... Ti consiglio di leggere qui (http://www.gnu.org/software/bash/manual/bash.html) per farti un'idea più precisa. Nella prima riga leggerai:
Bash is the GNU shell, or command language interpreter.
che vuol dire che bash è un linguaggio script, alla carlona lo puoi pensare come una estensione (ampia) dei file batch del DOS. Il suo linguaggio può sempbrare quello di un linguaggio di programmazione (come semantica) ma non lo è, quindi non lo puoi assolutamente paragonare al C++ o al Java quanto parli di "livelli" di linguaggio. so cos'è il bash perché lo sto studiando proprio in questo periodo per un esame; in questo thread naturalmente quando ho parlato di bash non mi sono riferito alla shell (cioè all'interprete del caso) ma al linguaggio da essa interpretato; e non vedo perché non possa essere considerato un linguaggio di programmazione... il JavaScript secondo te è un linguaggio di programmazione? be', è anche un linguaggio di scripting... lo stesso dicasi per il PHP... forse per te Bash non è un linguaggio di programmazione perché è interpretato? anche BASIC in molte sue manifestazioni è interpretato e non penso che gli si possa negare la definizione di linguaggio di programmazione...
che cos'è nel significato dell'espressione "linguaggio di programmazione" che non può essere applicato al linguaggio Bash?
[...] Poi con la JNI puoi fare un po' di tutto, ma questo esula dal Java puro che tu, da quello che ho capito ora, volevi trattare. e per forza :)
mettere in ballo JNI invalida tutto il discorso di questo thread perché significa che a quel punto il Garbage Collector può essere tranquillamente superato nella libreria nativa; questo mi pare ovvio, e se tu affermi che usando JNI è possibile commettere dei veri e propri leak da far rabbrividire la pelle (nonché le mie stecche di RAM :D) allora sono più che d'accordo.
No? Leggi il link che ho postato dietro :read: no cosa? :mbe:
e quale link? i thread lunghi sono ingestibili, a che pagina stava il link?
No no affatto. In molti cercano di classificare il medio livello, invece, anche se non è mai entrato di fatto come "voce di catalogazione". se non esiste una definizione ufficialmente accettata prendila come una definizione mia e di molti altri che ho spiegato con gli esempi del post che mi hai quotato.
Quindi Pascal che consente di manipolare i puntatori e di basso livello. . . no, non esageriamo, non ho mai detto questo; l'Object Pascal di Delphi lo considero di medio livello perché penso che abbia caratteristiche funzionali analoghe a quelle del C++.
Appunto... Delphi è di medio livello.... si
Ok. Ma "il bash" non è un linguaggio. BASH significa Bourne Again SHell ed è una shell. E' semplicemente uno scripting language che è diverso da un linguaggio di programmazione. perché non può essere considerato un linguaggio di programmazione? solo per l'estetica della sintassi?
Certo...infatti quello è solitamente l'ambiente principale del C... si, ma l'esempio del B-albero calza perfettamente anche in un contesto C++ ;)
hey! me ne vado un pomeriggio e mi scrivete dozzine di pagine?!! :D ci ho messo un pò a leggere! interessante l'esempio di fidel, ma effettivamente all'inizio non era molto chiaro il problema!
auguri mjordan :D
ps. IMHO i B-TREE stanno meglio nel C, no ti serve niente del C++.. o sbaglio?
cmq l'importante alla fine è intendersi :)
Quoto ;)
si, ma l'esempio del B-albero calza perfettamente anche in un contesto C++ ;)
Sì, ma di fatto diventa una istruzione su N-mila ;)
so cos'è il bash perché lo sto studiando proprio in questo periodo per un esame; in questo thread naturalmente quando ho parlato di bash non mi sono riferito alla shell (cioè all'interprete del caso) ma al linguaggio da essa interpretato; e non vedo perché non possa essere considerato un linguaggio di programmazione... il JavaScript secondo te è un linguaggio di programmazione? be', è anche un linguaggio di scripting... lo stesso dicasi per il PHP...
Mi avevi parlato di bash senza specificare che ti riferivi alla sua semantica, lasciando sottinteso questo concetto. In questo caso (sulla semantica) ne possiamo discutere: domani però, tra mezz'ora esco ;)
per te Bash non è un linguaggio di programmazione perché è interpretato?
Sì, tecnicamente non è un traduttore, ma un interprete. La differenza tra le due cose è nota, io però di solito chiamo "linguaggi di programmazione" i traduttori. Se tu invece ti riferisci alla semantica (interpretazione alla fine non errata, ma secondo me un po' fuorviante data la comune interpretazione) ne possiamo parlare, come dicevo prima. Del resto, gli script bash stilisticamente sembrano programmi C ;)
Ora puoi capire la mia posizione quando hai asserito "no, e un linguaggio di programmazione, e di alto livello" con molta convinzione, ma il tuo chiarimento non si è fatto attendere ;)
ps. IMHO i B-TREE stanno meglio nel C, no ti serve niente del C++.. o sbaglio? be' secondo me... sbagli! :D
qualsiasi tipo di grafo secondo me si realizza benissimo in un'ottica OOP: piuttosto che realizzare i nodi con le struct li realizzi con le classi, e quindi li puoi realizzare anche con una migliore eleganza formale; magari ad esempio puoi costruire un tuo set di classi usando come classe base una classe che rappresenti un grafo generico, poi da questa puoi distinguere grafi orientati e non, poi da quelli orientati derivi una serie di classi per rappresentare tutti i vari tipi di alberi, eccetera.
Sì, tecnicamente non è un traduttore, ma un interprete. appunto, ma come ho detto è così anche per molte implementazioni del BASIC, e non diresti mai che il BASIC non è un linguaggio di programmazione!
La differenza tra le due cose è nota, io però di solito chiamo "linguaggi di programmazione" i traduttori. Se tu invece ti riferisci alla semantica (interpretazione alla fine non errata, ma secondo me un po' fuorviante data la comune interpretazione) ne possiamo parlare, come dicevo prima. Del resto, gli script bash stilisticamente sembrano programmi C ;)
Ora puoi capire la mia posizione quando hai asserito "no, e un linguaggio di programmazione, e di alto livello" con molta convinzione, ma il tuo chiarimento non si è fatto attendere ;) be' ma non capisco tutta questa stranezza e insolitudine nel considerare il linguaggio Bash un linguaggio di programmazione... è talmente potente (per essere una shell) che ci si possono fare una miriade di cose che su Windows devono essere realizzate con necessariamente programmi appositi; gli script in Bash sono veri e propri programmi (interpretati naturalmente) che possono essere anche molto lunghi; per esempio al nostro corso il primo esonero consisteva nel creare esclusivamente in linguaggio Bash un clone del comando rsync... io vabbè non l'ho fatto perché ho fatto l'esame in modalità esame (non esoneri), però ho visto quello di un mio compagno (visto che tanto all'orale il prof mi deve fare un didietro così su Bash :cry: ) ed ammontava a un paio di centinaia di righe se ricordo bene. direi che il look and feel del linguaggio di programmazione c'è tutto :sofico:
C'è una incomprensione di fondo. Il problema risiede nel fatto che, ad esempio:
1) istanzio 'byteArray' da 10 mega e la uso
2) ho bisogno di un buffer più grosso: reistanzio byteArray da 20 Mb. i 10 mega di prima vengono subito rimossi, e ne vengono riallocati 20.
3) il GC rimuoverà i 20 mega solo quando vado a cancellare la classe!
Non è un memory leak classico, viene chiamato memory leak di tipo "object loitering", quel buffer viene tranquillamente eliminato quando rimuovo l'intera classe, ma nel frattempo sta lì a rubare inutilmente memoria.
Uhm, non lo considererei un leak, in fondo la memoria non viene persa, viene semplicemente messa da parte nella speranza che questo porti qualche vantaggio. Se quel metodo viene chiamata qualche decina di volte al secondo per file di dimensioni costanti, quella memoria è tutt'altro che inutilizzata. Dipende dall'uso che se ne fa.
Sì, tecnicamente non è un traduttore, ma un interprete. La differenza tra le due cose è nota, io però di solito chiamo "linguaggi di programmazione" i traduttori.
Un linguaggio è un linguaggio. Che poi venga dato in pasto ad un interprete o ad un traduttore è un altro paio di maniche. Tanto che alcuni vengono sia interpretati che tradotti. Oppure prima tradotti (in bytecode) e poi interpretati.
Va da sè che qualche linguaggio più si presta all'interpretazione (bash) che alla traduzione (C).
ekerazha
06-02-2006, 23:09
un conto sono le opinioni sugli argomenti, un conto sono le opinioni sulle persone
"per me quel che dici non si regge in piedi" è diverso da "per me non capisci un cazzo", concetto che hai espresso in altri termini (non così diversi) parecchie volte nei confronti dei tuoi interlocutori: se con un po' di calma e oggettività ti andrai a rileggere il topic coglierai dei toni aggressivi nei tuoi post
te lo dico in modo sterile, per evitare polemiche
Errato... io non ho mai insultato nessuno (e ti sfido a dimostrare il contrario citando mie parole). Posso essere stato aggressivo (sempre in modo garbato però) ma solo se precedentemente provocato. Quelli che hanno mosso per primi insulti personali sono stati altri... eppure te lo avevo già spiegato nel mio post numero #15.
Discorso concluso.
ekerazha
06-02-2006, 23:52
Piccola pausa per festeggiare il mio compleanno ... :p
Auguri.
Non è retorica, sono dei libri :p
Non l'elenco dei libri, ma le tue parole ed il tuo modo di porti.
Secondo alcuni ragionamenti che si sono fatti, anche Pascal allora dovrebbe essere di medio/basso livello? ;) Basta contare il numero di parole riservate per dare una stima approssimativa.
Nessuno ha mai parlato di "medio/basso", se mai di "medio/alto".
Io non ho detto che scrivi software banale, ho detto che chiunque partecipi in progetti non banali si rende conto che un bug (anche quelli piu' comuni) non dipendono esclusivamente dall' "attenzione", "cura del codice", "progettazione dell'architettura", tutte cose che tu invece hai elencato come "metodi" per eliminare simili bug. Il livello di attenzione, forte o debole che ognuno di noi ha, rimane "umano". Vista l'impossibilità di scrivere codice complesso senza introdurre bug comuni, è nata l'ingegneria del software. Disciplina che cerca di dare un metodo al processo. E nonostante ciò, non ha eliminato il problema. Da cui i libri che ti ho consigliato di leggere. Ti fanno rendere conto che magari esiste una complessità del software che, da come parli, evidentemente sembri ignorare. Tutto qui.
Ripeto per l'ennesima volta... nessuno mette in dubbio che non vi sia la possibilità di "scrivere codice complesso senza introdurre bug comuni", ma come già spiegato è possibile ridurne drasticamente il numero con i banali accorgimenti che tu hai ricordato. Nessuno dice che dipenda esclusivamente da questo, ma sicuramente gioca un ruolo importante.
E' inutile sfidarmi sul piano personale. Come non ti conosco io non mi conosci tu. Da dove proviene tutta questa certezza di "vincere"? ;)
Dalla bontà dei progetti a cui lavoro ;) :p
Posso scrivere una funzione completamente "bug free". Tuttavia il ruolo di una funzione va considerato anche sul piano semantico in relazione al codice complessivo. Quella funzione "bug free" potrebbe diventare completamente priva di senso in seguito a una modifica da un'altra parte del codice. Moltiplica il tutto per milioni di righe, strutture dati non banali che interagiscono fra loro, funzioni che si basano sul contenuto di una struttura che al minimo cambiamento diventano inconsistenti e ti rendi conto che il discorso "dell'attenzione" che facevi tu si continua ad applicare solo a software banale.
Dipende da come strutturi il codice. Premesso che non ho capito la tua affermazione "Quella funzione bug free potrebbe diventare completamente priva di senso in seguito a una modifica da un'altra parte del codice", qui risiede l'importanza di sviluppare (in modo miratamente curato) codice modulare ed altamente riutilizzabile. Sono sempre semplici accorgimenti ed ognuno preso singolarmente vale ben poco (nessuno mette in dubbio questo), ma è l'insieme di tutti questi accorgimenti che ci dà la possibilità, se non di eliminare (poichè l'uomo è fallibile per definizione), di ridurre drasticamente la possibilità d'errore nelle varie fasi dello sviluppo.
Il cervello umano riesce a gestire (male) un massimo di 3 cose contemporaneamente. E' la biologia che lo dice, non serve neanche considerare l'informatica.
Mah... qui servirebbe un bel ripasso sul funzionamento del cervello, dei neuroni, delle connessione sinaptiche etc. e la tua affermazione non ha molto a che vedere con questo... comunque non c'entra nulla col nostro discorso ;)
Se li leggi ti accorgi che non sono proprio elementari come li consideri... Come fai a stipulare un verdetto dai soli titoli... Un qualcosa prima di essere giudicato va letto. Il Fowler che ti ho dato non è proprio banale. Ti fa rendere conto che UML non è soltanto un class diagram. Il dragon Book all'unanimità è pure considerato un testo "difficile", non adatto ai principianti e l'ho preso proprio perchè ho visto un esperto come te.
Leggili.
Se trovo un libro dal titolo "Impariamo l'alfabeto" esso mi sembra abbastanza autoesplicativo sul suo contenuto :D Ho affermato ciò perchè leggendo i titoli mi sono reso conto che sono in gran parte argomenti che già conosco.
L'argomento trattato non è altro che una discussione che si basa su opinioni che invece hanno fondamento in quelle discipline. Da cui i libri che ti ho citato. Prima di discutere di qualcosa ci vuole fondamento.
Questi fondamenti penso siano già abbastanza noti alla maggior parte di noi (spero). Sarebbe stato maggiormente "risolutivo" un testo che trattasse esplicitamente l'argomento in questione, anche perchè a partire dai suddetti "fondamenti" poi ognuno può comunque dedurre una propria intepretazione delle cose e si è sempre al punto di partenza :)
UML non è soltanto costituito da Class diagram. UML può diventare terrificante. Certo non è difficile da imparare, ma provare a implementare qualcosa che risci a concepire in UML è un'altro "esercizio" per capire dove può arrivare la complessità del software. E che quindi il livello di "attenzione" non c'entra ancora nulla.
La complessità del codice non è necessariamente correlata alla quantità d'errori (certo può essere uno dei fattori... magari uno dei maggiori). Molti programmatori commettono errori ed ingenuità anche in programmi e algoritmi relativamente semplici. Credo che per evitare determinati errori language-related (non so... un buffer overflow in C piuttosto che una sql injection in PHP) sia il caso di lavorare direttamente sui linguaggi in questione più che su UML.
Come volevasi dimostrare
La "sicurezza" che hai proviene da due elementi di giudizio:
1) Sicurezza che in fondo non lo è.
2) Sicurezza certa dovuta a estrema semplicità del codice trattato.
Io credo che la tua sia un mix di entrambi i punti. 2000 righe di codice C/C++ inolte non sono proprio la stessa cosa che 2000 righe di codice PHP, vista "l'indulgenza sintattica" per cui questo linguaggio è famoso. Lo stesso dicasi per SQL.
Credo tu stia parlando senza conoscere bene PHP (senza offesa chiaramente... non voglio che si scateni un altro flame). Innanzitutto non ho ben capito cosa vorresti dire con i punti 1 e 2, ma in ogni caso le questioni sulla sicurezza del codice PHP che ho sollevato (a semplice titolo esemplificativo) non hanno *nulla* a che fare con la presunta "indulgenza sintattica" ma sono errori concettuali dovuti alla scarsa attenzione (nuovamente) dello sviluppatore. Come in C devo eseguire controlli relativi alla capienza del buffer (ad esempio) in PHP devo eseguire controlli relativi ai vari dati in input (inviati attraverso i metodi GET, POST o attraverso i COOKIES) per accertare che non possiedano "contenuti ostili". Tra l'altro questo non ha molto a che vedere con SQL... forse ti ha tratto in inganno la parola "sql injection", dato che questo tipo di vulnerabilità si evidenzia per una non corretta gestione di dati ricevuti in input dall'utente e poi passati al database sempre dal linguaggio di scripting (PHP) e non riguarda in maniera diretta il linguaggio SQL stesso.
:)
be' secondo me... sbagli! :D
qualsiasi tipo di grafo secondo me si realizza benissimo in un'ottica OOP: piuttosto che realizzare i nodi con le struct li realizzi con le classi, e quindi li puoi realizzare anche con una migliore eleganza formale; magari ad esempio puoi costruire un tuo set di classi usando come classe base una classe che rappresenti un grafo generico, poi da questa puoi distinguere grafi orientati e non, poi da quelli orientati derivi una serie di classi per rappresentare tutti i vari tipi di alberi, eccetera.
si effettivamente è comoda la rappresentazione del grafo OO! non so se ci sono differenze prestazionali in grafi particolarmente grossi (come gli alberi dei FS), però senza dubbio è più elegante!
comunque non ho capito ancora la definizione esatta che vuoi dare al medio livello... anche perchè se consideri solo il fatto dei puntatori nel medio livello ci devi mettere anche il C# oltre al delphi come diceva cionci... non mi convince ancora sta cosa.. io personalmente non mi sono mai sbilanciato più di tanto, ma se proprio ci metterei C, COBOL, FORTRAN & CO! non tanto per il fatto di gestire in un certo tipo la memoria, ma per il fatto che non contemplano la programmazione OO, che di per sè stravolge l'approccio che il programmatore ha con il linguaggio! in questo senso l'OOP permette di astrarre ad un livello più alto i concetti.. in maniera più vicina a quello che fa l'uomo in un certo senso! se però adesso arriva uno e mi chiede dove mettere lisp o prolog... non saprei cosa rispondere! quindi credo che una definizione di medio livello sia un tantino più complessa di quello che sembra.. poi ho sentito parlare addirittura di medio/basso medio/alto livello :doh: sarebbe già troppo definire il medio livello!
ekerazha
07-02-2006, 00:03
poi ho sentito parlare addirittura di medio/basso medio/alto livello :doh: sarebbe già troppo definire il medio livello!
Questo perchè ogni linguaggio possiede proprie sfumature... non penso vi siano linguaggi perfettamente equivalenti ad altri (e se ci fossero non penso abbiano molto senso d'esistere) :)
Questo perchè ogni linguaggio possiede proprie sfumature... non penso vi siano linguaggi perfettamente equivalenti ad altri (e se ci fossero non penso abbiano molto senso d'esistere) :)
si ma dalle sfumature stabilire se uno è a un livello superiore di un altro è un altro conto! ti ho detto.. già non è ancora chiaro il passaggio da alto livello a medio... vuoi che sia chiaro quello da medio a medio/basso? :confused: ho già detto che il GC non basta a rendere un linguaggio di più alto livello rispetto al C++ ad esempio.. o almeno la cosa non mi convince!
ekerazha
07-02-2006, 00:54
si ma dalle sfumature stabilire se uno è a un livello superiore di un altro è un altro conto! ti ho detto.. già non è ancora chiaro il passaggio da alto livello a medio... vuoi che sia chiaro quello da medio a medio/basso? :confused: ho già detto che il GC non basta a rendere un linguaggio di più alto livello rispetto al C++ ad esempio.. o almeno la cosa non mi convince!
Io non ho mai parlato di medio/basso :-P Io considero di basso livello l'Assembly (se vogliamo scendere ancora più in basso possiamo trovare il codice binario :p ). Chiaramente la cosa si presta a svariate interpretazioni (come sta dimostrando questo thread) ed anche volessimo riunire alcuni linguaggi in una determinata fascia, anche tra linguaggi appartenenti ad una stessa fascia vi sarebbero comunque alcune differenze o sfumature :)
Errato... io non ho mai insultato nessuno (e ti sfido a dimostrare il contrario citando mie parole).
giusto per esser preciso:
Come vedi è possibile rispondere a tono senza insultare l'interlocutore sul piano personale... ed è davvero singolare che debba spiegartelo uno più giovane (dato che sei già laureando) e teoricamente più immaturo di te.
Per cortesia risparmiami questi patetici esercizi di retorica.
Se le argomentazioni sono le stesse che hai portato tu, credo sia meglio non buttare i soldi ;)
quei libri (dai titoli) sembrerebbero abbastanza "basilari" (tranne "Ingegneria del software", materia tra l'altro trattata nel corso di Ingegneria Informatica) e mi sembrerebbero più adatti ad un pubblico come te :)
Io spero davvero stiate scherzando, altrimenti siete messi male... ma davvero malissimo...
... mi sembra davvero di essere capitato fra un manipolo di pazzi...
volevo dire la stessa cosa su di te ma non l'ho detto perchè a differenza tua ho un briciolo di educazione e maturità e cerco di non alimentare flame inutilmente.
Cresci.
Bravo. Dopo aver dimostrato scarsa competenza con i tuoi errori grossolani mentre tentavi di addentrarti in argomenti che esulano dalla tua conoscenza ed il tentativo di "invenzione" della lingua italiana, l'unico modo che hai per dare una parvenza di intelligenza è proprio quella di non parlare :)
Sei solo un poveraccio :)
Tutte castronerie a cui non hai saputo contrapporre la minima argomentazione convincente se non fraintendendo le cose che venivano dette e commettendo errori come già detto grossolani
Occasione che non è stata altro che la punta di un enorme iceberg: il tuo scarso ed imbarazzante livello di competenza.
Per il resto c'è ben poco da trolleggiare.
Le ultime parole famose di un uomo coerente ;)
ma se continui a rimuginare è segno che evidentemente hai la "coscienza sporca" (ed in effetti è probabile che sia così) :)
Mi pare evidente come il tuo concetto di "dimostrare" sia assolutamente ridicolo e risibile, non avendo argomentato davvero nulla che sia anche lontanamente riconducibile alla pallida controfigura di una dimostrazione.
Io dico semplicemente quello che penso e cioè che tu sia un programmatore pessimo e di scarsissima competenza... e come già detto non lo dico per offenderti ma è quello che penso in realtà e i motivi che mi hanno condotto a questo pensiero te li ho fatti notare più e più volte :)
Ma tu continui a non capire fraintendendo di proposito le mie parole (e denotando anche una scarsa conoscenza dell'italiano) poichè le tue sciocche argomentazioni non potrebbero scalfire minimamente ciò che affermo effettivamente e sei quindi costretto a ricorrere a questi "giochetti" di tenore davvero basso.
:)
E' incredibile come nella mia "giovane vita", fra tutti i programmatori che ho conosciuto (alcuni dei quali lavorano come già detto in grandi multinazionali), i peggiori li possa incontrare insieme e nello stesso forum. E' una coincidenza stranissima.
se vuoi vado avanti
se consideri l'insulto in senso stretto, tipo "sei un cretino", beh, c'è pure questo, da "sei solo un poverccio" in poi
se invece, come ritengo più corretto, si considera l'insulto in senso lato, metà delle parole che hai scritte le hai spese così, per dire - estrapolandone il succo - che gli altri sono cretini
comunque, chiuso il discorso, sarei curioso di vedere un po' di codice php scritto da te
Dopo questo incredibile riassunto di FX, mi sa che mi disiscrivo dalla discussione... Dovessi passare qualche settimana a farmi rigirare continuamente i post.
ekerazha
07-02-2006, 09:34
giusto per esser preciso:
se vuoi vado avanti
se consideri l'insulto in senso stretto, tipo "sei un cretino", beh, c'è pure questo, da "sei solo un poverccio" in poi
se invece, come ritengo più corretto, si considera l'insulto in senso lato, metà delle parole che hai scritte le hai spese così, per dire - estrapolandone il succo - che gli altri sono cretini
comunque, chiuso il discorso,
Per l'appunto... nessuno di quelli che hai citato sono insulti volgari... quelli che tu chiami "insulti in senso lato" sono semplici considerazioni personali, assolutamente non volgari.
Inoltre ti consiglio di far caso a chi ha iniziato ad attaccare per primo l'interlocutore sul piano personale... ti consiglio di rileggere nuovamente il mio post #15 in modo da evitare di continuare questa sterile conversazione.
sarei curioso di vedere un po' di codice php scritto da te
Credo sia una curiosità condivisibile.
A tutti: per favore smettiamola...
Mi piace giocare con i puntatori ;)
e siccome (se la memoria non m'inganna) il compilatore non permette di addizionare due puntatori (che nell'esempio del B-albero sarebbero un indirizzo base e un offset), è necessario prima convertire a interi (possibilmente senza segno) e poi di nuovo a puntatori ;)
Non t'inganna infatti, il compilatore non permette di addizionare direttamente due puntatori, però puoi fare il tutto senza passaggi intermedi, con un bel cast ad 'unsigned long int'.
Es:
#define UINT unsigned long int
...
char *pointer1, *pointer2;
UINT result;
...
result = (UINT)pointer1 + (UINT)pointer2;
Si può anche "estremizzare" il tutto:
#define UINT unsigned long int
...
char *pointer1, *pointer2, *respointer;
...
(UINT)respointer = (UINT)pointer1 + (UINT)pointer2;
In quest'ultimo esempio, però, il compilatore (testato con gcc 3.3.3) tira fuori il seguente warning:
warning: use of cast expressions as lvalues is deprecated
deprecato, ma funziona :D Di solito evito però questo secondo approccio.
EDIT: nel secondo approccio, si può togliere (seguendo il warning) il cast di respointer, salvo poi avere un warning diverso:
warning: assignment makes pointer from integer without a cast
Eh per forza....
Uhm, non lo considererei un leak, in fondo la memoria non viene persa, viene semplicemente messa da parte nella speranza che questo porti qualche vantaggio. Se quel metodo viene chiamata qualche decina di volte al secondo per file di dimensioni costanti, quella memoria è tutt'altro che inutilizzata. Dipende dall'uso che se ne fa.
Per questa considerazione ti riporto ai post precedenti ;)
be' ma non capisco tutta questa stranezza e insolitudine nel considerare il linguaggio Bash un linguaggio di programmazione... è talmente potente (per essere una shell) che ci si possono fare una miriade di cose che su Windows devono essere realizzate con necessariamente programmi appositi; gli script in Bash sono veri e propri programmi (interpretati naturalmente) che possono essere anche molto lunghi; per esempio al nostro corso il primo esonero consisteva nel creare esclusivamente in linguaggio Bash un clone del comando rsync... io vabbè non l'ho fatto perché ho fatto l'esame in modalità esame (non esoneri), però ho visto quello di un mio compagno (visto che tanto all'orale il prof mi deve fare un didietro così su Bash :cry: ) ed ammontava a un paio di centinaia di righe se ricordo bene. direi che il look and feel del linguaggio di programmazione c'è tutto :sofico:
Sì, come detto prima, se la metti sul piano semantico e funzionale, bash è paragonabile ad un linguaggio di programmazione, come altri linguaggi scripting del resto. Il discorso che facevo io era un po' più sottile, semplicemente rimarcavo la differenza tra traduttore ed interprete. Bash infatti, giustamente si appoggia su comandi esterni precompilati (spesso di default in una installazione Unix, ma non sempre), tranne che per alcune funzioni built-in, ma come "modo di programmare" e come funzionalità convengo. A questo punto, come esempio ancora più calzante prenderei il TCL, che pur essendo interpretato, nasce come linguaggio di programmazione, con librerie e tutto. Lo stesso interprete TCL può essere usato come libreria C... E' solo una questione di terminologia, normalmente cerco di essere preciso per evitare fraintesi ;)
Ancora sui "memory leaks" in Java. Spulciando tra la mia documentazione, cartacea e non, sull'argomento, mi sono imbattuto in questo post (preso da forum.java.sun.com) molto significativo, che parla proprio di come normalmente si intende il "memory leak" in java (non proprio in senso "tradizionale"). Ammetto che l'autore di questo testo possiede un dono di sintesi migliore del mio (;)):
Striktly speaking there could be no memory leaks in java than those known from C/C++.
A java "memory leak" is more like holding a strong reference to an object though i would never be needed anymore. The fact that you hold a strong reference to an object prevents the GC from deallocating it.
Think of an array of objects, think of a get/put protocoll on that array (stack like). You would have something like a highwater mark on your stack.
Say you have a (sketched) get method like
public Object get() {
highWaterMark--;
return stackArray[highWaterMark];
}
what happens after 5 inserts and 3 gets...
You have a situation like this in your stackArray.
stackArray[0] = obj0
stackArray[1] = obj1
stackArray[2] = obj2 <- highWaterMark
stackArray[3] = obj3
stackArray[4] = obj4
Note that indexes 2,3 and 4 still reference objects because our get method has not cleared those array members.
Although no other party might have a strong reference to those objects the GC can't collect them because the array is still holding a strong reference.
The rule is: In any composed object free, i.e. set to null, all references to part objects as soon as possible.
"Correct" version of our stack's get method is:
public Object get() {
highWaterMark--;
final Object result = stackArray[highWaterMark];
stackArray[highWaterMark] = null; //clearing a strong reference
return result;
}
EDIT: Si potrebbe risolvere penso anche utilizzando diversi tipi di reference oltre quello strong tramite il package 'java.lang.ref'.
Fidel prima hai postato dei link riguardo ai memory leak in Java per caso? Ora non ho troppo tempo di leggere, mica me li potresti raggruppare in un post? :sofico:
Grazie.
Fidel prima hai postato dei link riguardo ai memory leak in Java per caso? Ora non ho troppo tempo di leggere, mica me li potresti raggruppare in un post? :sofico:
Grazie.
Certo, non c'è problema :)
Ho iniziato con questo:
http://www-128.ibm.com/developerworks/library/j-leaks/
per me è un buon articolo, anche se un po' datato (2001).
Poi ho fatto un altro esempio che avevo studiato dai vari whitepapers IBM che mi arrivano su CD, e cionci ha trovato il link al sito IBM che li contiene:
http://www-128.ibm.com/developerworks/java/library/j-jtp01246.html
Da quel sito è possibile anche "saltare" ad altri articoli che trattano lo stesso tema, con soluzioni diverse.
Inserisco anche il link del manuale del package 'java.lang.ref', che fornisce metodi piuttosto raffinati per evitare i "memory leaks" java (influenzando limitatamente il GC):
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ref/package-summary.html
Questo invece è l'indirizzo di un thread di un forum Java che tempo fa ho salvato su HD. Meno male che mi segno gli indirizzi ;) Ho provato ed è ancora online:
http://forum.java.sun.com/thread.jspa?threadID=456545&start=0&tstart=0
Mi pare siano tutti.
Ciao ;)
EDIT: per tutti, sempre da forum sul sito della Sun, c'è anche quest'altro bel thread sui memory leaks Java:
http://forum.java.sun.com/thread.jspa?forumID=31&threadID=446934
Fossi in voi lo leggerei ;) davvero un caso "malefico" :D
Certo, non c'è problema :)
Ho iniziato con questo:
http://www-128.ibm.com/developerworks/library/j-leaks/
per me è un buon articolo, anche se un po' datato (2001).
Poi ho fatto un altro esempio che avevo studiato dai vari whitepapers IMB che mi arrivano su CD, e cionci ha trovato il link al sito IBM che li contiene:
http://www-128.ibm.com/developerworks/java/library/j-jtp01246.html
Da quel sito è possibile anche "saltare" ad altri articoli che trattano lo stesso tema, con soluzioni diverse.
Inserisco anche il link del manuale del package 'java.lang.ref', che fornisce metodi piuttosto raffinati per evitare i "memory leaks" java (influenzando limitatamente il GC):
http://java.sun.com/j2se/1.4.2/docs/api/java/lang/ref/package-summary.html
Questo invece è l'indirizzo di un thread di un forum Java che tempo fa ho salvato su HD. Meno male che mi segno gli indirizzi ;) Ho provato ed è ancora online:
http://forum.java.sun.com/thread.jspa?threadID=456545&start=0&tstart=0
Mi pare siano tutti.
Ciao ;)
EDIT: per tutti, sempre da forum sul sito della Sun, c'è anche quest'altro bel thread sui memory leaks Java:
http://forum.java.sun.com/thread.jspa?forumID=31&threadID=446934
Fossi in voi lo leggerei ;) davvero un caso "malefico" :D
Ottimo grazie mille. :)
^TiGeRShArK^
08-02-2006, 11:42
Ancora sui "memory leaks" in Java. Spulciando tra la mia documentazione, cartacea e non, sull'argomento, mi sono imbattuto in questo post (preso da forum.java.sun.com) molto significativo, che parla proprio di come normalmente si intende il "memory leak" in java (non proprio in senso "tradizionale"). Ammetto che l'autore di questo testo possiede un dono di sintesi migliore del mio (;)):
mmm...
cmq secondo me sono sempre dovuti ad errori concettuali...
a me ad esempio non sarebbe mai venuto in mente di usare un array per memorizzare degli oggetti il cui numero non è noto a priori, ma anzi tende a variare col passare del tempo...
la prima cosa che mi verrebbe in mente è utilizzare un ArrayList e usare i metodi get e remove...
un'implementazione ancora migliore è però ovviamente di usare la classe stack che è già fornita da java :D
in questo modo si risolve alla base il problema del memory leak e si evita lo sbattimento di reiplementare codice già esistente ;)
mmm...
cmq secondo me sono sempre dovuti ad errori concettuali...
a me ad esempio non sarebbe mai venuto in mente di usare un array per memorizzare degli oggetti il cui numero non è noto a priori, ma anzi tende a variare col passare del tempo...
la prima cosa che mi verrebbe in mente è utilizzare un ArrayList e usare i metodi get e remove...
un'implementazione ancora migliore è però ovviamente di usare la classe stack che è già fornita da java :D
in questo modo si risolve alla base il problema del memory leak e si evita lo sbattimento di reiplementare codice già esistente ;)
Vero, ma il problema è che memory leaks e simili sono sempre errori di programmazione o di design (a meno che non sono buggate le librerie o nel caso di Java la JVM). Poi ci sono modi di programmare che portano più facilmente ad errori di memoria ed altri meno secondo me ;)
^TiGeRShArK^
08-02-2006, 12:31
Vero, ma il problema è che memory leaks e simili sono sempre errori di programmazione o di design (a meno che non sono buggate le librerie o nel caso di Java la JVM). Poi ci sono modi di programmare che portano più facilmente ad errori di memoria ed altri meno secondo me ;)
yes.. ma in C ci sono molti piu' modi per capitare in un memory leak senza nemmeno rendertene conto...
in java quelli ke hai portato fino ad ora come esempio li avrei evitati di default, senza nemmeno fare considerazioni sul memory leak, per come sono abituato a programmare.....
in C onestamente qalke difficoltà in + c'è :p
yes.. ma in C ci sono molti piu' modi per capitare in un memory leak senza nemmeno rendertene conto...
in java quelli ke hai portato fino ad ora come esempio li avrei evitati di default, senza nemmeno fare considerazioni sul memory leak, per come sono abituato a programmare.....
in C onestamente qalke difficoltà in + c'è :p
Questo è poco ma sicuro! :D Non a caso ci sono diverse librerie C++ che implementano i GC per semplificarti la vita, oppure in modo più semplice senza usare un GC ci sono gli smart pointer (il template auto_ptr in testa).
Anch'io in Java normalmente non faccio "memory leaks", ma in un paio di occasioni mi è capitato, niente di gravissimo trattando con sistemi da un Giga di memoria, ma ad alto rischio considerando che erano applicazioni eseguite h24... Purtroppo capita anche quello (ah, gli esempi riportati erano "memory leaks" particolarmente evidenti eh! ;))
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.