[RISOLTO] problemi con new e delete

Ciao a Tutti...scusate se il post sarà lungo...

antefatto:
tempo fa provai ad utilizzare, a scopo "didattico", l'allocazione dinamica della memoria con new e delete...e senza problemi funzionò; i due operatori erano presenti (visibili) all'interno dello stesso if(); quindi avevo una cosa del tipo:

  if (verifica) {
    int *p_int = new int[quanti];
    ...
    delete [] p_int;
  }

cosa mi serve:
adesso ho necessità di maneggiare stringhe di lunghezza variabile a seconda della situazione...nel caso specifico...a video, e su lcd, stampo una domanda che avrà una risposta di lunghezza variabile.
ho creato quindi un array di puntatori per le domande ed un array per le risposte...quindi domanda e risposta stessa posizione nelle array.
A seconda della domanda che pongo vado a verificare la lunghezza della risposta e creo una nuova stringa con"new" di pari lunghezza; in questa nuova stringa vado a salvare le "lettere" inserite come risposta per confrontare la risposta inserita con quella attesa.
le domande possono essere eseguite in modo sequenziale o in modo casuale...quindi ho creato due condizione nello sketch: RANDOM == true; RANDOM == false.

cosa faccio:
come detto le domande possono essere poste in sequenza nella lista od in modo casuale...ed all'interno di queste due condizioni vado ad allocare la memoria dinamicamente;per fare questo ho dichiarato il puntatore nelle globali come "char *p_string;"; all'interno delle due condizioni con un ciclo for() vado a contare quanto lunga è la risposta (verifico posizione per posizione fino a trovare '\0'); alloco la memoria con "p_string = new char[lunghezzaRisposta];"...inserisco nelle varie posizioni di p_string il carattere digitato da tastierino...dopo la verifica, in teoria, libero la memoria con "delete p_char".

cosa ottengo (problema):
facendo un po' di debug con stampa a monitor ho visto che: all'inizio la lunghezza della risposta veniva fatta correttamente e quindi allocavo spazio corretto; l'assegnazione dei singoli caratteri veniva fatta correttamente e la verifica con la stringa originale era ok...il problema era la seconda domanda...pur contando la lunghezza corretta della seconda risposta il p_string manteneva la lunghezza della prima creazione (delete non eseguito!?)...dopo senza modificare alcun che ...p_string ha assunto lunghezze fuori controllo :slightly_frowning_face:

di cosa sono sicuro(?):
le varie fasi del programma vengono eseguite tutte anche quelle che includono il delete (debug a monitor seriale); la verifica della lunghezza della risposta viene eseguito correttamente ogni volta (debug); la lunghezza dell'allocazione varia dai 5 ai 12 bytes; lo sketch occupa il 4% della memoria e le varibili globali l'8%...uso una MEGA (non originale).

cose di cui non sono sicuro e che non ho provato:
data la mia ignoranza in materia mi è venuto il dubbio che il puntatore p_string debba comunque essere un int per gestire l'indirizzo puntato...in questo caso dovrei scrive una cosa tipo(?):

int *p_string = new char[numero];

oppure...al posto di new e delete si deve usare malloc()/calloc() e free()?

grazie

Come detto millemila volte usare la memoria dinamica su una piccola mcu 8 bit, con pochissima ram senza nulla che provvede a gestirla in modo efficiente, non solo è volersi fare del male da soli, ma è anche un ottimo modo per andare incontro a crash imprevedibili, quasi sempre molto difficili da diagnosticare/debuggare.
Premesso quanto sopra, la soluzione è semplicemente usare un singolo, dueo se realmente necessario, buffer ram, dichiarato come "char myarray]n]" dove n è la lunghezza massima + 1 della stringa che dovrà contenere, e operare esclusivamente su questo.
Ti rammento che una stringa di caratteri viene, deve essere, sempre terminata con 0x00, questo permette di conoscere la sua reale lunghezza anche se il buffer che la contiene ha una dimensione maggiore.

Concordo ovviamente con Astro, ma se proprio vuoi proseguire per quella strada (di nuovo: sconsigliato), allora usa direttamente la classe String, che è fatta apposta.

Se poi vuoi capire cosa non va nel tuo codice, per pura curiosità, postalo per intero.

Intanto grazie delle risposte...

...è volersi fare del male da soli, ma è anche un ottimo modo per andare incontro a crash imprevedibili

Si...letto gli n-mila, forse gli n-cento, post e cosciente di ciò...sto tentando questa via in quanto:
il programma farà solo ed esclusivamente questo...quindi con "molto" spazio libero (magari sbaglio ragionamento); la memoria da allocare a runtime varia da 5 a 12 bytes (sempre pensando che dovrei avere spazio); considerando questi primi due punti volevo fare pratica con l'allocazione dinamica.

...usa direttamente la classe String

all'inizio, durante la fase di pseudo ragionamento di come sviluppare il codice, ho pensato di usare le String...ma come detto qualche riga prima, visto il programma, ho pensato di fare pratica con l'allocazione...se non dovessi risolvere/capire l'inghippo convertirò il tutto.

Per il codice, appena posso, vedo di postarlo.
grazie

ORSO2001:
la memoria da allocare a runtime varia da 5 a 12 bytes (sempre pensando che dovrei avere spazio);

Il problema non è tanto quanta ram libera hai, è che continue riallocazioni della ram portano inevitabilmente alla scrittura di parti già in uso, al overflow della ram o del heap/stack, cose che causano risultati imprevedibili, si spazia da dati con valori diversi da quanto dovrebbe essere fino al crash del software.

... e niente eh ... proprio non vi entra in testa che NON siete su un PC dove c'è un sistema operativo ed un "garbage collector" e che le varie funzioni di new(), mallo(), free() realloc(), ecc. su piccoli sistemi così sono implementate al minimo e che il crash e sempre dietro l'angolo.

Su questi "giocattolini", ma anche su MCU un po' più serie, l'allocazione dinamica è sempre meglio evitarla ...

... se vuoi divertirtici, scaricati un ambiente di sviluppo sul tuo PC e giocaci li ... almeno c'è il sistema operativo che tiene d'occhio i casini che combini :smiley: :smiley: :smiley:

Guglielmo

proprio non vi entra in testa che NON siete su un PC

diciamo che a volte, forse anche troppo spesso, se mi confronto con un blocco di marmo quest'ultimo può risultare molto più plasmabile... :smiley:

comunque Astro mi ha ricordato una cosa di cui mi ero dimenticato e cioè dopo:

p_string = new char[rispostaLength];

ho aggiunto:

p_string[rispostaLength -1] = 0x00;

e funziona...

Cavolo, volevo suggerirtelo anch’io, ma davo per scontato che ci avessi già pensato! :-[

Comunque, in tal caso è meglio che allochi la stringa di lunghezza rispostaLength + 1.

ciao Sukko...ci avevo pensato in fase di "progettazione" ma poi nella pratica me ne sono dimenticato (convinto, al momento, di averlo fatto...quando le cose le fai alla sera tardi va così :smiley: )...nella array delle risposte il terminatore è presente quindi rispostaLength lo conta (verificato :wink: ) e ritorna la lunghezza totale.

oppure mi stai consigliando di allocare una posizione (byte) in più!?

Voglio solo dire che se devi memorizzare una stringa di 10 caratteri, ad esempio, devi allocarne 11. Altrimenti, mettendo il terminatore nell'ultimo, tagli un carattere.