Newsgroup: it.comp.lang.c++
Titolo: la memoria non poteva essere "read" - portabilita'

Ciao ragazzi,
premettendo di essere abbastanza nuovo per quanto riguarda la
programmazione,il mio problema è il seguente:
sviluppato un semplice software (x win) sul portatile, girava che era
un amore ma a malincuore ho notato che sul mio desktop, cosi' come
anche su altri, in apertura di un mio file,da quel spiacevole errore
<< l'istruzione ha fatto riferimento all'indirizzo #... la memoria non
poteva essere "read" >> (stessa versione di win).
Non so piu' dove sbattere la testa, su internet ho trovato qualcosa
riguardo problemi di overflow di buffer, ho controllato e
ricontrollato il codice ma sembra proprio che non ci siano problemi
( infatti sul laptop va! ).
Grazie a tutti anticipatamente.
Francesco.

p.s.: scusate gli errori sintattici e ortografici, ma l'ora e' tarda e
non ho riletto :P

sli...@libero.it
 ha scritto:

Dovresti controllare se la funzione o metodo che utilizzi per aprire il 
file ti restituisce un errore dovuto all'assenza del file stesso nella 
cartella dove il tuo programma lo cerca.
Nel caso che tu faccia una lettura o scrittura su un file che non è 
stato possibile aprire, potresti avere un errore simile a quello che 
descrivi, dal sistema operativo (windows nel tuo caso).
Magari nel tuo portatile il file da aprire si trova nella stessa 
cartella dell'eseguibile e questo errore non lo hai mai avuto.
Prova a ripetere il test sul tuo portatile (non in debug), cancellando o 
rinominando il file da aprire e vedi cosa succede.
Maurus

Non so piu' dove sbattere la testa
Generalmente questi problemi sono dovuti all'uso di puntatori non
inizializzati. Fammi vedere un po' di codice e ti saprň dire meglio.

bool Lista::Load(){ //Legge tutti gli oggetti salvati in backup.dat
    Persona * p = new Persona;
    ifstream file;
    int size = sizeof(Persona);
    //if(file.open(backup,ios::noreplace|ios::binary|ios::in));
    file.open(backup,ios::binary|ios::in);
    if(file){
        file.seekg(0,ios::beg);
        while(file.read(reinterpret_cast<char *>(p),size)){
            Load(p);
        }
        file.close();
        delete p;
        return true;
    }
    else return false;
}
---
Gia' fatto quel tipo di prove, non dipende dal file.. il debugger (di
visual c++) mi parla di un certo puntantore pHead, nn ci ho capito
granke'.. da notare che anche in un progetto analogo che sto
sviluppando ora in cui sfrutto la stessa classe, mi da questo errore:
"DAMAGE: after normal block (#numero) at 0x047.."
ci sto perdendo la testa davvero ragazzi..

 }
Io fossi in te riscriverei questa parte del programma. Stai facendo cose che 
non dovresti fare e non solo questo, ma il programma ti dara' sempre 
problemi, specilmente se provi di generare il file su un sistema A e poi 
leggere il file su sistema B. Basta aver un O.S. diverso o un compilatore 
diverso o ancora i settaggi del compilatore un tantino diversi e' succede un 
casino. La rappresentazione binaria di Persona non e' garantita in C++, ogni 
compilatore puo' fare quello che vuole e lo stesso compilatore puo' decidere 
di fare cose diverse a seconda che tua sia in debug mode, oppure che hai 
selezionato una opzione diverse per l'alignment, etc...
In fine il codice e' troppo low level, reinterpret_cast<>, puntatori raw, 
etc...
Se anche risolvessi il tuo problema, questo codice rimarrebbe cmq una 
soluzione non buona al tuo problema. Quindi io non cercherei nemmeno di 
risolvere il problema (che con un debugger dovrebbe essere cmq banale 
trovare), ma inizierei a ri-scrivere il codice...
Ci sono varie opzioni. Se non hai problemi grossi di prestazioni nel 
leggere/scrivere sul/dal file, come e' di solito, potresti anche usare un 
formato testuale che sia facilmente ispezionabile, quindi anche xml.
Spero di esserti stato di aiuto.
Tommaso

 Tommaso
Ci sono anche altri problemi con il tuo codice, anche restando sullo stesso 
sistema, con stesso compilatore e settings, etc...
Supponi che Persona abbia:
- 1 array di caratteri di dimensioni fisse
- 1 intero
il codice tuo ha piu' o meno senso, ma supponi che Persona ora sia:
- un puntatore ad una stringa da qualche altra parte in memoria
- 1 intero
Beh, ora il problema e' che sul file salvi l'indirizzo a cui punta il 
puntatore, non la stringa. Quando leggi dal file tale stringa potrebbe non 
esistere in memoria o se anche esiste potrebbe essere in un altro indirizzo.
Questo problema non lo hai solo se usi puntatori direttamente, ma ad esempio 
anche se usi vector (std::vector<char> invece di un array di caratteri ad 
esempio).... nonostante puoi mettere il vector all'interno della classe, il 
vector gestira' poi un array che verra' allocato nella heap e questo non 
verra' salvato.
Ovviamente per gesitre le stringhe dovresti usare std::string e.... lo 
stesso problema lo avresti anche usando std::string.
Tommy

Sono uno studente al primo anno di ingegneria informatica. Come mai
non e' garantita la rappresentazione binaria in c++?
Questa è l'unica strada che ho trovato per scrivere/leggere su memoria
di massa, non ho esperienza di xml.
Poi perche' troppo basso livello? Su tutti i libri che ho letto, il
casting va fatto proprio in quel modo (nel mio caso); cosa sarebbero i
puntatori "raw"?
Cmq e' ovvio che leggendo da file non tengo conto dei puntatori..ogni
volta carico una lista linkata in memoria, da file mi
serve solo leggere stringhe fondamentalmente, membri di una mia
classe.
Scusa l'ignoranza :P

p.s.: questo e' l'errore causato da un altra applicazione mfc (che sto
sviluppando con visualc++)
http://img517.imageshack.us/my.php
?
image=errordamagedx8.jpg quando uso quel metodo.. (clicco ignora e il
resto va alla perfezione).

 puntatori "raw"?
il casting in quanto tale può anche essere giusto, è la parte di codice
che lo usa che è completamente sbagliata. Devi pensare ad un livello
più alto.
Quindi se:
struct Persona
{
  string nome;
  string cognome;
}
dovrai preoccuparti di leggere da file il nome e poi assegnarlo
all'opportuno membro, la stessa cosa con cognome.
Ciao
-- 
Andrea Corradi | Debian User | 
www.debian.org
Fingerprint: A41E F6B0 DBDB F04C 4940 E411 30F3 CD62 57B1 8458
gpg --keyserver 
keyserver.linux.it
 --recv-key 57B18458
Please avoid sending me Word or PowerPoint attachments.
http://www.gnu.org/philosophy/no-word-attachments.html

 non e' garantita la rappresentazione binaria in c++?
Lo Standard offre solo alcune garanzie limitatamente agli oggetti di tipo
POD [1]. In questo caso, lo Standard ti permette di copiare la sequenza di
byte che compone l'oggetto in un array e ripristinarla successivamente,
oppure copiarla direttamente in un altro oggetto dello stesso tipo. Se
l'oggetto non è di tipo POD tali operazioni hanno effetti indefiniti.
Sospetto che il tuo "Persona" non sia POD.
In ogni caso, se queste garanzie possono avere qualche utilità o
applicazione, non è certo per implementare meccanismi di serializzazione.
Ti consiglio di approfondire la questione leggendo qualcosa e facendo
qualche ricerca ("serialization"). Le C++-FAQ-Lite hanno una capitolo
dedicato alla serializzazione [2], che può essere un buon punto di
partenza.
Max
[1] 
http://www.fnal.gov/docs/working-groups/fpcltf/Pkg/ISOcxx/doc/POD.html
[2] 
http://www.parashift.com/c++-faq-lite/serialization.html

 wrote

Una immagine con l'errore non basta. Per capire per bene l'errore serve come 
minimo il codice e lo stack trace dell'errore.
Tommy

 membri di una mia classe.
ti hanno gia' risposto in modo preciso gli altri, quindi mi limito a 
chiederti... per stringa cosa intendi?! un array di chars o una std::string?
Tommy

grazie ragazzi per le risposte che mi avete dato, ora do un occhiata
alla serializzazione e riscrivo cmq il codice interessato, lavorando
in testuale e non binario.. Ora che ci penso, se fondamentalmente devo
leggere/scrivere solo stringhe, non ho bisogno di complicarmi la vita
oprando in binario per salvare l'intero oggetto ( che non mi serve
nella sua totalita ).
Anche se a questo punto mi chiedo.. se lo standard offre solo
determinate garanzie in merito, come mai su tutto il materiale che ho
letto, nessuno ne faceva cenno e riportavano tutti lo stesso metodo,
che ho tra l'altro usato io, per scrivere oggetti su memoria di massa?
Per Tommaso: per stringhe intendo stringhe, array di caratteri, non
oggetti std::string.
Grazie ancora ragazzi :)

 che ho tra l'altro usato io, per scrivere oggetti su memoria di massa?
Perchè una buona parte dei materiali che si trovano in giro fanno
piuttosto schifo. Questa è la risposta breve.
La risposta lunga è: dipende caso per caso, specie in dipendenza da
quello che hai capito tu.
Comunque basta che tu pensi che perfino per una cosa cretina come un
intero non c'è una fava di garanzia. Su alcuni sistemi sono 4 byte, su
altri 8 byte (e volendo potrebbe variare ancora). In alcuni sistemi è
big-endian, in altri little-endian.
Il motivo per cui lo standard non da garanzie sul layout degli oggetti è
semplicemente per motivi di efficienza. Scegliere big-endian o
little-endian come *obbligatorio* penalizzerebbe le architetture
diverse, idem fissare uno standard di dimensione. Oltretutto piattaforme
diverse possono avere diversi vincoli sull'allineamento (e/o diversa
efficienza o possibilità per accedere certi tipi di dato a certi
allineamenti).
Di fatto o sali di livello (Python) accettando di perdere efficienza,
oppure te la smazzi con C++ e introduci (se e quando necessario) strati
software intermedi (che pure ti fanno perdere efficienza, ovviamente, ma
solo "se e quando necessario"). In compenso aumenti i tempi di sviluppo.
E' tutto un compromesso.
-- 
-riko