Newsgroup: it.comp.lang.c++
Titolo: Allocazione di array dinamici e loro deallocazione

Se alloco un array di caratteri dinamicamente nel seguente modo:
char *p;
int n;
p = new(char[n]);
per deallocare successivamente la memoria e' sufficiente fare:
delete p;
oppure occorre deallocare singolarmente gli elementi dell'array come segue:
for (i=1; i<=n; i++)
  delete &(p[i]);
Inoltre gli array allocati dinamicamente permettono una scansione del tipo:
char *p1;
for (p1 = p; p1<=(p+n); p1++)
  delete p1;
Ringrazio anticipatamente chi mi vorra' dare una risposta.
--
Posted from 
mta03-acc.tin.it
 [212.216.176.34]
via Mailgate.ORG Server - 
http://www.mailgate.org

 delete p;
delete [] p;
EMG

 delete p;
delete [] p;
-- 
Maurizio Loreti                      
http://wwwcdf.pd.infn.it/~loreti/mlo.html
Un. of Padova, Dept. of Physics - Padova, Italy          
lor...@padova.infn.it

 
for(char* p1=p; p<p+n; ++p1)
  /* fa qualcosa */
non usare comunque p1 per fare una delete, in generale e` un errore che
paghi quando fai "delete[] p"
Saluti,
Paolo
-- 
------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
 
http://www.cli.di.unipi.it/~marotta
  G: Potreste commentare l'attuale
     panorama informatico?
  I: /* l'attuale panorama informatico */
------------------------------------------------

   delete &(p[i]);
Nessuna delle due. Per deallocare un array si fa:
  delete [] p;
La delete senza [] dealloca solo un elemento.
Il ciclo non funziona: la delete si puo' applicare solo agli indirizzi 
restituiti da new, in questo caso solo p.  Tutti gli indirizzi da p+1
a p+n-1 si trovano all'interno di un blocco di memoria e non possono 
essere deallocati singolarmente.
	Mauro

...

E per deallocarli singolarmente, come bisognerebbe allocarli?
San Vegeta from Hell
http://www.geocities.com/Area51/Dungeon/8436

Paolo
Volevo aggiungere che scrivendo
for(char* p1=p; p<p+n; ++p1)
bisognerebbe assicurarsi che n non faccia sballare le dimensioni dell'array.
Infatti i char occupano 1 byte, mentre gli int 4: se p1 puntasse a interi e
n non fosse un multiplo intero di 4 si verificherebbero degli errori.
Correggetemi se ho sbagliato.
Bruno

 E per deallocarli singolarmente, come bisognerebbe allocarli?
Uno alla volta, con new "normale", senza []
Ognuno ha il suo puntatore, e puo' essere deallocato, pero' non
e' detto che gli indirizzi siano consecutivi (e di solito non lo
sono).
Se ti serve un array di elementi (de)allocabili singolarmente ci
vuole un array di puntatori:
  Object ** p = new Obejct* [MAX];
  for (int i = 0; i < MAX; ++i)
    p[i] = new Object(...);
  // p[i]->x invece di p[i].x
  // delete p[i];
  for (int i = 0; i < MAX; ++i)
    delete p[i];
  delete [] p;
Per i char non ne vale la pena, e adesso neanche per gli oggetti grandi:
molto meglio usare std::vector
	Mauro

 e char!!! ( compilatore g++, egc++, Digital C++ )
Posso sbagliare, ma a me risulta che la sintassi
p = new( placement );
serva per creare un oggetto dinamico all'indirizzo specificato e non
possa essere utilizzata al posto della
p = new char [ n ];
EMG

E per deallocarli singolarmente, come bisognerebbe allocarli?
Dovresti prima allocarli singolarmente e non in blocco.
Paolo
------------------------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
  home:   
http://www.cli.di.unipi.it/~marotta
  G: Per concludere, possiamo chiedervi di commentare
     l'attuale panorama informatico?
  I: /* l'attuale panorama informatico */
------------------------------------------------------------------

Correggetemi se ho sbagliato.
Mi avevi quasi fatto saltare dalla sedia :-(
In effetti c'e` un piccolo errore, ma non e` quello che pensi tu...
dovevo scrivere:
for(char* p1=p; p1<p+n; ++p1)
                              ^^
Anche perche` chiaramente p<p+10 e` sempre vera (ergo loop infinito...).
Per quanto riguarda l'operazione p+n essa e` sempre corretta, in questo caso
non esegui una addizione su interi, ma una operazione su puntatori e l'aritmetica
dei puntatori dice che p+n==&(p[n] )...
Saluti,


>> p = new(char[n]);
veramente la forma sarebbe new(void* p) ed e` la sintassi di placement...


delete [] p;
Uhm.. anche a me risultava che per i tipi primitivi non ce ne fosse
bisogno. Ho sempre omesso il [] in questi casi e non ho mai avuto
problemi di memory leaks dovuti a questo.
___
Fabio Forno
"Vi aspetta l'esplorazione delle ignote possibilita' 
dell'esistenza" - Q in "All Good Things..."
=============================================
scia...@inorbit.com


Sono d'accordo. E assolutamente vero. Io volevo notare che per un sotto
insieme
del compilatore che io conosco ( VC, g++, egs++, CodeWarrior, alcune
compilatore nativi ) per diverse piattoforme : ( NT, SunOS, Linux, RT
LynxOS, WinCE, DEC VMS,
DEC OSF ) la realizazzione del delete e delete[] per i puntatore a "flat
objects" e identica. Guardate assembly code per i "flat objects" source1,2 e
per oggetti
con construttore/distruttore (source/code 3).
Nel caso 1,2 va chiamato operatore delete, nel caso 3
call  ??_EA@@QAEPAXI@Z ; A::`vector deleting destructor'
cio si passail punt. a oggetto, size e IL PUNTATORE AD DESTRUCTOR.
Practicamente compilatore riconosce cosa deve distruggere e genera il codice
appropriata.
Source 1 :
----------------------
void main()
{
 char* pChar = new char[8];
 delete[] pChar;
}
----------------------
Source 2 :
void main()
{
 char* pChar = new char[8];
 delete pChar;
}
----------------------
Code 1 :
<skipped>
; 3    :  char* pChar = new char[8];
  00018 6a 08   push  8
  0001a e8 00 00 00 00  call  ??2@YAPAXI@Z  ; operator new
  0001f 83 c4 04  add  esp, 4
  00022 89 45 f8  mov  DWORD PTR $T224[ebp], eax
  00025 8b 45 f8  mov  eax, DWORD PTR $T224[ebp]
  00028 89 45 fc  mov  DWORD PTR _pChar$[ebp], eax
; 4    :  delete[] pChar;
  0002b 8b 4d fc  mov  ecx, DWORD PTR _pChar$[ebp]
  0002e 89 4d f4  mov  DWORD PTR $T225[ebp], ecx
  00031 8b 55 f4  mov  edx, DWORD PTR $T225[ebp]
  00034 52   push  edx
  00035 e8 00 00 00 00  call  ??3@YAXPAX@Z  ; operator delete
  0003a 83 c4 04  add  esp, 4
; 5    : }
<skipped>
--------------------------
Code 2 :
; 3    :  char* pChar = new char[8];
  00018 6a 08   push  8
  0001a e8 00 00 00 00  call  ??2@YAPAXI@Z  ; operator new
  0001f 83 c4 04  add  esp, 4
  00022 89 45 f8  mov  DWORD PTR $T224[ebp], eax
  00025 8b 45 f8  mov  eax, DWORD PTR $T224[ebp]
  00028 89 45 fc  mov  DWORD PTR _pChar$[ebp], eax
; 4    :  delete pChar;
  0002b 8b 4d fc  mov  ecx, DWORD PTR _pChar$[ebp]
  0002e 89 4d f4  mov  DWORD PTR $T225[ebp], ecx
  00031 8b 55 f4  mov  edx, DWORD PTR $T225[ebp]
  00034 52   push  edx
  00035 e8 00 00 00 00  call  ??3@YAXPAX@Z  ; operator delete
  0003a 83 c4 04  add  esp, 4
; 5    : }
-----------------------
e adesso per il ojjetto con construttore/destruttore :
---------- source ----------
class A
{
public :
 A()
 {
  m_pChar = new char[8];
 };
 ~A()
 {
  delete m_pChar;
 }
private :
 char *m_pChar;
};
void main()
{
 A* pA = new A[8];
 delete[] pA;
}
----------------
Code :
; 18   :  A* pA = new A[8];
  0002d 6a 24   push  36   ; 00000024H
  0002f e8 00 00 00 00  call  ??2@YAPAXI@Z  ; operator new
  00034 83 c4 04  add  esp, 4
  00037 89 45 e8  mov  DWORD PTR $T260[ebp], eax
  0003a c7 45 fc 00 00
 00 00   mov  DWORD PTR __$EHRec$[ebp+8], 0
  00041 83 7d e8 00  cmp  DWORD PTR $T260[ebp], 0
  00045 74 2e   je  SHORT $L261
  00047 68 00 00 00 00  push  OFFSET FLAT:??1A@@QAE@XZ ; A::~A
  0004c 68 00 00 00 00  push  OFFSET FLAT:??0A@@QAE@XZ ; A::A
  00051 8b 45 e8  mov  eax, DWORD PTR $T260[ebp]
  00054 c7 00 08 00 00
 00   mov  DWORD PTR [eax], 8
  0005a 6a 08   push  8
  0005c 6a 04   push  4
  0005e 8b 4d e8  mov  ecx, DWORD PTR $T260[ebp]
  00061 83 c1 04  add  ecx, 4
  00064 51   push  ecx
  00065 e8 00 00 00 00  call  ??_L@YGXPAXIHP6EX0@Z1@Z ; `eh vector
constructor iterator'
  0006a 8b 55 e8  mov  edx, DWORD PTR $T260[ebp]
  0006d 83 c2 04  add  edx, 4
  00070 89 55 dc  mov  DWORD PTR -36+[ebp], edx
  00073 eb 07   jmp  SHORT $L262
$L261:
  00075 c7 45 dc 00 00
 00 00   mov  DWORD PTR -36+[ebp], 0
$L262:
  0007c 8b 45 dc  mov  eax, DWORD PTR -36+[ebp]
  0007f 89 45 ec  mov  DWORD PTR $T259[ebp], eax
  00082 c7 45 fc ff ff
 ff ff   mov  DWORD PTR __$EHRec$[ebp+8], -1
  00089 8b 4d ec  mov  ecx, DWORD PTR $T259[ebp]
  0008c 89 4d f0  mov  DWORD PTR _pA$[ebp], ecx
; 19   :  delete[] pA;
  0008f 8b 55 f0  mov  edx, DWORD PTR _pA$[ebp]
  00092 89 55 e0  mov  DWORD PTR $T264[ebp], edx
  00095 8b 45 e0  mov  eax, DWORD PTR $T264[ebp]
  00098 89 45 e4  mov  DWORD PTR $T263[ebp], eax
  0009b 83 7d e4 00  cmp  DWORD PTR $T263[ebp], 0
  0009f 74 0f   je  SHORT $L265
  000a1 6a 03   push  3
  000a3 8b 4d e4  mov  ecx, DWORD PTR $T263[ebp]
  000a6 e8 00 00 00 00  call  ??_EA@@QAEPAXI@Z ; A::`vector deleting
destructor'
  000ab 89 45 d8  mov  DWORD PTR -40+[ebp], eax
  000ae eb 07   jmp  SHORT $L266
$L265:
  000b0 c7 45 d8 00 00
 00 00   mov  DWORD PTR -40+[ebp], 0
$L266:
----- class A code ------------
; 4    :  A()
  00000 55   push  ebp
  00001 8b ec   mov  ebp, esp
  00003 83 ec 48  sub  esp, 72   ; 00000048H
  00006 53   push  ebx
  00007 56   push  esi
  00008 57   push  edi
  00009 51   push  ecx
  0000a 8d 7d b8  lea  edi, DWORD PTR [ebp-72]
  0000d b9 12 00 00 00  mov  ecx, 18   ; 00000012H
  00012 b8 cc cc cc cc  mov  eax, -858993460  ; ccccccccH
  00017 f3 ab   rep stosd
  00019 59   pop  ecx
  0001a 89 4d fc  mov  DWORD PTR _this$[ebp], ecx
; 5    :  {
; 6    :   m_pChar = new char[8];
  0001d 6a 08   push  8
  0001f e8 00 00 00 00  call  ??2@YAPAXI@Z  ; operator new
  00024 83 c4 04  add  esp, 4
  00027 89 45 f8  mov  DWORD PTR $T281[ebp], eax
  0002a 8b 45 fc  mov  eax, DWORD PTR _this$[ebp]
  0002d 8b 4d f8  mov  ecx, DWORD PTR $T281[ebp]
  00030 89 08   mov  DWORD PTR [eax], ecx
; 7    :  };
  00032 8b 45 fc  mov  eax, DWORD PTR _this$[ebp]
  00035 5f   pop  edi
  00036 5e   pop  esi
  00037 5b   pop  ebx
  00038 83 c4 48  add  esp, 72   ; 00000048H
  0003b 3b ec   cmp  ebp, esp
  0003d e8 00 00 00 00  call  __chkesp
  00042 8b e5   mov  esp, ebp
  00044 5d   pop  ebp
  00045 c3   ret  0
??0A@@QAE@XZ ENDP     ; A::A
_TEXT ENDS
; COMDAT ??1A@@QAE@XZ
_TEXT SEGMENT
_this$ = -4
$T284 = -8
??1A@@QAE@XZ PROC NEAR     ; A::~A, COMDAT
; 9    :  {
  00000 55   push  ebp
  00001 8b ec   mov  ebp, esp
  00003 83 ec 48  sub  esp, 72   ; 00000048H
  00006 53   push  ebx
  00007 56   push  esi
  00008 57   push  edi
  00009 51   push  ecx
  0000a 8d 7d b8  lea  edi, DWORD PTR [ebp-72]
  0000d b9 12 00 00 00  mov  ecx, 18   ; 00000012H
  00012 b8 cc cc cc cc  mov  eax, -858993460  ; ccccccccH
  00017 f3 ab   rep stosd
  00019 59   pop  ecx
  0001a 89 4d fc  mov  DWORD PTR _this$[ebp], ecx
; 10   :   delete m_pChar;
  0001d 8b 45 fc  mov  eax, DWORD PTR _this$[ebp]
  00020 8b 08   mov  ecx, DWORD PTR [eax]
  00022 89 4d f8  mov  DWORD PTR $T284[ebp], ecx
  00025 8b 55 f8  mov  edx, DWORD PTR $T284[ebp]
  00028 52   push  edx
  00029 e8 00 00 00 00  call  ??3@YAXPAX@Z  ; operator delete
  0002e 83 c4 04  add  esp, 4
; 11   :  }
------------------

 problemi di memory leaks dovuti a questo.
In effetti per molti compilatori nel caso di tipi primitivi delete
e delete[] possono essere utilizzati con lo stesso effetto, tuttavia
la cosa non e` standard e sarebbe bene non approfittarne, non
sarebbe difficile che un domani ci si possa pentire della cosa.
Paolo
-- 
------------------------------------------------
  Paolo Marotta
  Computer Science, University of Pisa
 
http://www.cli.di.unipi.it/~marotta
  G: Potreste commentare l'attuale
