n° 219
Novembre 2017
Dicembre 12, 2017, 09:30:53 *
Benvenuto! Accedi o registrati.
Hai dimenticato l'e-mail di attivazione?

Accesso con nome utente, password e durata della sessione
Notizia:
 
   Indice   Linux Windows Techassistance Gameassistance videogame hardware Aiuto Ricerca Agenda Downloads Accedi Registrati  


* Messaggi recenti
Messaggi recenti
Pagine: [1]   Vai giù
  Stampa  
Autore Discussione: Usare un puntatore d'appoggio per evitare un errore "invalid pointer"  (Letto 1245 volte)
0 utenti e 1 Utente non registrato stanno visualizzando questa discussione.
vuott
Newbie
*

Karma: +2/-1
Scollegato Scollegato

Messaggi: 31


Mostra profilo
« inserita:: Maggio 12, 2017, 12:15:47 »

In questo semplice codice all'interno della funzione "fnz( )" non ho inteso utilizzare alcuna particolare funzione standard per assegnare un testo alla variabile "s":
Codice:
#include <stdio.h>
#include <stdlib.h>


void fnz (char **s) {

*s = "testo qualsiasi";
}


int main() {

char *t = calloc(16, sizeof(char));

fnz(&t);

printf("%s\n", t);

free(t);

    return (0);

}
pertanto debbo passare alla predetta funzione "fnz( )" l'indirizzo di memoria del puntatore "t".

Il problema sorge con la funzione "free( )" che mi solleva un errore "munmap_chunk(): invalid pointer". Infatti, andando a leggere l'indirizzo di memoria della variabile "t" prima e dopo la chiamata della funzione "fnz( )", esso è diverso.


Allora, come soluzione estrema, per liberare l'area di memoria precedentemente riservata e puntata dal Puntatore "t", ho pensato di usare un Puntatore d'appoggio ("r"), al quale assegnare il Puntatore "t", in modo tale che anche tale variabile d'appoggio "r" punti alla medesima area di memoria riservata e già puntata da "t".
Così alla funzione "free( )" ho passato quella variabile "r":
Codice:
#include <stdio.h>
#include <stdlib.h>


void fnz (char **s) {

*s = "testo qualsiasi";
}


int main() {

char *r, *t = calloc(16, sizeof(char));
r=t;

fnz(&t);

printf("%s\n", t);

free( r);

    return (0);

}
Così facendo non ho ottenuto alcun errore.


Ritenete possa considerarsi corretta ed esauriente sotto ogni profilo la soluzione da me adottata ?   Imbarazzato

Grazie
Registrato
oregon
Jr. Member
**

Karma: +22/-6
Scollegato Scollegato

Messaggi: 239


Mostra profilo
« Risposta #1 inserita:: Maggio 12, 2017, 03:12:31 »

In realtà stai commettendo un errore (banale) qui

*s = "testo qualsiasi";

Dovresti scrivere

strcpy(*s, "testo qualsiasi");
Registrato
vuott
Newbie
*

Karma: +2/-1
Scollegato Scollegato

Messaggi: 31


Mostra profilo
« Risposta #2 inserita:: Maggio 12, 2017, 05:28:56 »

Sì, oregon, ne sono consapevole; ed infatti ho chiarito che la scelta di non usare una apposita funzione (come appunto la strcpy( )) è stata coscientemente voluta, seppur per soli fini meramente sperimentali e di studio.

Ad ogni modo, avendo dunque voluto forzare il codice (e ritenuto comunque più adeguata, coerente e da adottarsi la consueta soluzione dell'uso di una specifica funzione come la "strcpy( )"), mi domandavo semplicemente se l'altra soluzione (con il Puntatore d'appoggio) sortisce in pratica i medesimi effetti desiderati di deallocazione dell'area di memoria precedentemente riservata.
Registrato
oregon
Jr. Member
**

Karma: +22/-6
Scollegato Scollegato

Messaggi: 239


Mostra profilo
« Risposta #3 inserita:: Maggio 12, 2017, 06:33:00 »

No ... c'è un problema di fondo.

Una costante stringa come

"testo qualsiasi"

è allocata come sequenza di caratteri all'interno dell'eseguibile ed è rappresentata da un puntatore che punta a tale porzione di zona dati dell'exe.

Quando scrivi

*s = "testo qualsiasi";

non fai altro che perdere il valore precedente del puntatore (*s) assegnandogli il valore del puntatore costante di cui ti ho detto.

E' per questo che la free ti dà un errore dato che non può utilizzare il puntatore così modificato.

In pratica, tu allochi la memoria nell'heap tramite un puntatore xyz, poi perdi 1234 assegnando il valore 5678 e tenti di liberare 5678 ottenendo due errori, 1) non puoi liberare la memoria del puntatore a testo costante e 2) crei un memory leak perché il puntatore allocato in precedenza lo perdi.

Con il metodo che hai indicato tu non fai che mettere "una pezza", salvando il tuo puntatore originale e ripristinandolo in modo da poterlo offrire correttamente alla free. Ma è altrettanto sbagliato perché non stai utilizzando la memoria allocata in quanto la stringa non viene trasferita in quella zona di memoria.
Te ne accorgi se, con questo metodo, tenti di cambiare un carattere della stringa dopo averla assegnata ...

Ecco perché la cosa corretta da fare è, allocando della memoria, spostare i caratteri in questa, con o senza funzione strcpy, ti basta anche un ciclo for con due puntatori sorgente e destinazione, ma NON con una assegnazione tra puntatori.

Registrato
vuott
Newbie
*

Karma: +2/-1
Scollegato Scollegato

Messaggi: 31


Mostra profilo
« Risposta #4 inserita:: Maggio 13, 2017, 01:20:06 »

Su questa prima parte del tuo intervento concordo e non ho dubbi:

Quando scrivi

*s = "testo qualsiasi";

non fai altro che perdere il valore precedente del puntatore (*s) ..........


Però su quanto esposto da qui:

.... non stai utilizzando la memoria allocata in quanto la stringa non viene trasferita in quella zona di memoria....
in poi vi è qualcosa che mi sfugge e che non riesco a comprendere. Per chiarire la natura dei mei dubbi e delle mie perplessità, vorrei tornare al precedente codice integrandolo nella parte mediana della routine principale come segue:
Codice:
......
printf("%p   %p\n", r, t);

fnz(&t);

printf("%p   %p\n", r, t);
......
per vedere l'indirizzo di memoria contenuto da entrambe le variabili "r" e "t" prima e dopo il passaggio della variabile "t" alla funzione "fnz( )".

Ebbene, risulta che (riportando come esempio pratico i valori effettivi che mi compaiono ora in console) i due Puntatori "prima" del passaggio posseggono entrambi il seguente medesimo valore:
0xa93010   0xa93010
Questi valori si riferiscono ovviamente all'area di memoria allocata appena precedentemente con la funzione "calloc( )". Cosicché, volendo deallocare quell'area, suppongo che - considerando il codice fino a quel punto - si possa passare all'apposita funzione "free( )" indifferentemente il Puntatore "t" o il Puntatore "r".
 
Invece "dopo" il passaggio alla funzione "fnz( )" quei Puntatori riportano due valori diversi (come del resto hai preannunciato tu nel tuo secondo intervento), che nel mio caso concreto appaiono tali:
r ---> 0xa93010
t ---> 0x400734

Ora, preso atto (per le motivazioni già da te riportate e spiegate) che il puntatore "t" punta ormai ad una differente area di memoria, immagino che l'area di memoria precedentemente allocata sia rimasta comunque allocata, poiché a me sembra che nessuna funzione o particolare circostanza sia intervenuta ad effettuare la deallocazione.
Immagino anche che l'indirizzo di memoria di quell'area rimasta lì "appesa", allocata, sia ancora quello precedente, ossia nel mio caso riportato esemplificativo: 0xa93010 .

La mia prima domanda è: se dunque io passo alla funzione "free( )" questo indirizzo di memoria, che si riferisce alla iniziale area di memoria allocata con la funzione "calloc( )", tale area non verrà forse de-allocata ?
Se la risposta è eventualmente affermativa, l'altra domanda è: quale è il Puntatore attualmente contenente l'indirizzo di memoria di quell'area ancora allocata ? Ovviamente il Puntatore "r" (ed esso solo, dato che la variabile "t", come sappiamo, punta ormai ad altri luoghi della memoria).
Ergo, mi sorge per deduzione spontaneamente la terza domanda: se passo il Puntatore "r" alla funzione "free( )", non determino forse, dunque, la deallocazione di quell'area ?
Registrato
oregon
Jr. Member
**

Karma: +22/-6
Scollegato Scollegato

Messaggi: 239


Mostra profilo
« Risposta #5 inserita:: Maggio 13, 2017, 06:22:33 »

Va bene tutto ma resta il fatto che "non stai utilizzando" l'area di memoria ma semplicemente la allochi e la deallochi.

Come ti ho detto prima, se veramente la usassi, al suo interno troveresti le singole lettere della frase.
Prova ad usare il puntatore 0xa93010 per ottenere o modificare i singoli caratteri e fai lo stesso con il puntatore 0x400734 ed esamina i risultati in dettaglio.

Forse tu fai confusione tra il concetto di puntatore e di area di memoria puntata.

Registrato
vuott
Newbie
*

Karma: +2/-1
Scollegato Scollegato

Messaggi: 31


Mostra profilo
« Risposta #6 inserita:: Maggio 13, 2017, 03:53:29 »

Forse tu fai confusione tra il concetto di puntatore e di area di memoria puntata.
Penso... di no, poiché tu mi hai ben fatto notare e spiegato che dalla funzione invocata in poi il Puntatore "t" (come evidenziano anche i valori da me riportati) punta ormai altrove, ossia in altro indirizzo della memoria dove sono stati scritti i valori afferenti ai caratteri, mentre nell'area di memoria, che fu dinamicamente allocata, non è stato memorizzato nulla di nuovo (e non lo sarà fino al termine del programma).
Ed infatti se io pongo questa riga:
Codice:
printf("%s\n   %s\n", t, r);
si verifica quanto da te spiegato, poiché per l'argomento "r" viene stampato il solo carattere "\n" prossimo alla corrispondente direttiva di conversione.


"non stai utilizzando" l'area di memoria
Questo dunque l'ho compreso e ti ringrazio per avermelo fatto notare e spiegato.


semplicemente la allochi e la deallochi.
Era appunto quanto io cercavo di comprendere con questo post.


Ho dunque ottenuto da te due chiarimenti

Ti ringrazio molto.


P.S.: ad ogni modo comprendo bene anche le tue perplessità, quando sostanzialmente dici: " a cosa serve allocare un'area di memoria, se poi non viene utilizzata ? ".    Bocca cucita
Registrato
Pagine: [1]   Vai su
  Stampa  
 
Vai a:  

Copyright © 2017 Edizioni Master SpA. p.iva : 02105820787

Tutti i diritti di proprietà letteraria e artistica riservati. - Privacy



powered by Simple Machines