Posizione librerie Visual C++

Strumenti informatici per la matematica applicata, le simulazioni, il disegno: Mathcad, Matlab, Scilab, Microcap, PSpice, AutoCad ...

Moderatori: Foto Utenteg.schgor, Foto Utentedimaios

Avatar utente
Foto Utentelellus
10 4
New entry
New entry
Messaggi: 57
Iscritto il: 27 ott 2013, 15:36
0
voti

[21] Re: Posizione librerie Visual C++

Messaggioda Foto Utentelellus » 10 apr 2016, 16:47

Ho studiato per bene il passaggio per valore e per riferimento(in realtà avevo già letto di cosa si trattava ma la cosa che mi risultava strana era che nella chiamata si passasse qualcosa che non era stata inizializzata). Ora rileggo con attenzione la tua risposta in modo da avere le idee più chiare. Intanto ti ringrazio per la pazienza e per la gentilezza.

Avatar utente
Foto Utentedimaios
30,2k 7 10 12
G.Master EY
G.Master EY
Messaggi: 3381
Iscritto il: 24 ago 2010, 14:12
Località: Behind the scenes
0
voti

[22] Re: Posizione librerie Visual C++

Messaggioda Foto Utentedimaios » 10 apr 2016, 17:50

lellus ha scritto: ...ma la cosa che mi risultava strana era che nella chiamata si passasse qualcosa che non era stata inizializzata


Ottimo. =D> . Questo è un punto importante. :ok:
Anche se si dichiara il puntatore dell'oggetto in una classe e poi si delega la sua generazione ad un altro oggetto non è buona cosa non inizializzare il puntatore, anzi è uno degli errori più classici.

Nel C++ 98 si inizializzava con il valore "0" oppure a seconda delle definizioni nei vari compilatori trovavi cose tipo "NULL" oppure "null" o altro.
Finalmente nel C++ 11 questa variazione sul tema non esiste più visto che è stato introdotto il concetto di nullptr che finalmente non lascia spazio ad equivoci.

Come potrai leggere in questo thread anche il padre del C++ Bjarne Stroustrup concorda nel suo utilizzo.
Ingegneria : alternativa intelligente alla droga.

Avatar utente
Foto Utentelellus
10 4
New entry
New entry
Messaggi: 57
Iscritto il: 27 ott 2013, 15:36
0
voti

[23] Re: Posizione librerie Visual C++

Messaggioda Foto Utentelellus » 30 apr 2016, 14:23

Continuo ad assillarvi con nuove domande :D Ho preso ulteriore dimestichezza con il linguaggio e mi è stato chiesto di instanziare un oggetto della classe CMRBSysDecoder con il seguente costruttore:

Codice: Seleziona tutto

CMRBSysDecoder::CMRBSysDecoder(FILE *Gmatfile,
                    int max_MRB_iterations,
                    int *CodeDimension,
                    int order_input,
                    double threshold,   
                    int TEP_file_flag,
                    char *TEP_file_name,
                    int min_dist)

Il file relativo alla matrice G da passare come primo parametro l'ho messo tra i file risorse in Visual Studio. Tra le risorse c'è anche il file .ini in cui una riga recita:

Codice: Seleziona tutto

Matrice-G = 16.12.listGmat.txt


la stringa 16.12.listGmat.txt è stata memorizzata nel campo Value di una variabile kvGmat di tipo KeyString dove keyString è la seguente struct:

Codice: Seleziona tutto

struct KeyString {[code][/code]
    char *Key;
    char *Value;
};


KeyString kvGmat è a sua volta un membro della struct SimParameters. Successivamente nel programma viene inizializzato un puntatore fSimPars a SimParameters in modo da poter scrivere:

Codice: Seleziona tutto

fSimPars->kvGmat.Value


Fin qui tutto ok perché ho usato il debug e verificato le variabili.

La parte di codice che ho scritto per istanziare il decoder e passare il file è:

Codice: Seleziona tutto

FILE *Gmatrix;
   char *fgmat;
    fgmat = new char[32];
   strcpy(fgmat,fSimPars->kvGmat.Value);
    Gmatrix = fopen(fgmat,'r');
   
   *dpmrbdecoder = new CMRBSysDecoder(Gmatrix,
                                    (fSimPars->MRBmaxI).Value,
                                    dimension,
                     (fSimPars->MRBOrder).Value,
                     (fSimPars->MRBThreshold).Value,
                     (fSimPars->TEP_orig).Value,
                      fSimPars->TEP_list_file.Value, 
                      (fSimPars->MinDist).Value);
   fclose(Gmatrix);
   delete[] fgmat;


Mi da un errore su fopen che recita: error C2664: 'fopen': impossibile convertire il parametro 2 da 'char' a 'const char *'
1> La conversione da tipo integrale a tipo puntatore richiede reinterpret_cast, cast di tipo C o cast di tipo funzione

Non capisco cosa sbaglio e cosa dovrei correggere. Sicuramente ci saranno diversi errori e spero mi possiate aiutare a venirne a capo. Grazie

Avatar utente
Foto Utentefairyvilje
15,0k 4 9 12
G.Master EY
G.Master EY
Messaggi: 3047
Iscritto il: 24 gen 2012, 18:23
Contatta:
0
voti

[24] Re: Posizione librerie Visual C++

Messaggioda Foto Utentefairyvilje » 30 apr 2016, 16:55

Usa "r" e non 'r'. Caratteri e stringhe non sono la stessa cosa :)
Guardati il prototipo di fopen per capire quali sono i tipi da usare o ascolta gli errori di compilazione :mrgreen:
"640K ought to be enough for anybody" Bill Gates (?) 1981
Qualcosa non ha funzionato...

Lo sapete che l'arroganza in informatica si misura in nanodijkstra? :D

Avatar utente
Foto Utentedimaios
30,2k 7 10 12
G.Master EY
G.Master EY
Messaggi: 3381
Iscritto il: 24 ago 2010, 14:12
Località: Behind the scenes
0
voti

[25] Re: Posizione librerie Visual C++

Messaggioda Foto Utentedimaios » 30 apr 2016, 22:43

Ci sono diversi problemi di programmazione in quello che hai scritto.

1. L'oggetto CMRBSysDecoder dovrebbe essere istanziato tramite uno smart pointer e non un puntatore nudo. I puntatori nudi sono molto pericolosi e con i nuovi paradigmi di programmazione fondamentalmente vietati.
In particolare :

Codice: Seleziona tutto

std::shared_ptr<CMRBSysDecoder> dpmrbdecoder  =  std::make_shared( ..... constructor args ..... );


In questo modo sei sicuro di deallocarlo al momento giusto ( non serve la delete perché lo smart pointer sa quando farla e la esegue quando nessuno possiede più la risorsa ).
A parte la sintassi iniziale per l'allocazione dpmrbdecoder lo usi come un puntatore classico ( ma ha anche metodi interessanti per fare cose che per ora non ti servono ).

2. perché fai la open del file fuori dall'oggetto CMRBSysDecoder ?

Codice: Seleziona tutto

Gmatrix = fopen(fgmat,'r');


Questa cosa è pericolosa perché se qualcosa va storto all'interno del costruttore scateni un'eccezione che non gestisci per cui non chiamerai mai

Codice: Seleziona tutto

fclose(Gmatrix);


Passa il nome del file come parametro al costruttore di CMRBSysDecoder e lui farà tutto quello che serve all' interno.
Se programmi ad oggetti, la prima cosa da fare è capire quali sono le funzioni da assegnare ad una classe.
Se il caricamento della matrice è una competenza di CMRBSysDecoder allora l'oggetto deve essere in grado di farlo in modo autonomo.

3. Questo frammento di codice

Codice: Seleziona tutto

   char *fgmat;
    fgmat = new char[32];
   strcpy(fgmat,fSimPars->kvGmat.Value);


... in C++ non si dovrebbe proprio scrivere.
Utilizza le std::string e tutto risulta più facile.
Cerca di non usare la sintassi C quando puoi impiegare oggetti della standard library per risolvere il problema.

4. Questa struttura ...

Codice: Seleziona tutto

struct KeyString {
    char *Key;
    char *Value;
};


Sarebbe meglio

Codice: Seleziona tutto

struct KeyString {
    std::string key   ;
    std::string value ;
};


In questo modo eviti le new e le malloc che hanno il problema del rilascio della memoria in caso di interruzione anomala del programma.

Un programmatore C++ non utilizza neanche la struct ma preferisce per vari motivi una class.

5. La funzione dovrebbe essere corredata dagli indispensabili try catch altrimenti non è sicura e non riesci a fare un debug efficace.

Codice: Seleziona tutto


bool functionName( params )
{
  try{
      ....
      //Scrivi il tuo codice qui ....
     ....
      return true ;
   }
   catch( std::exception& exc ){
     //Se viene generata un'eccezione ....
     
     cout << "Exception : " << exc.what() << std::endl;
     return false ; 
  }
}




6. In C++ si evitano i FILE e si usano gli stream.
Utilizzando gli stream se qualcosa va storto nella lettura lo stream viene deallocato automaticamente all'uscita dallo scope della funzione evitando leakage di memoria.


Poi ci sarebbero anche altre considerazioni ma per ora bastano queste per apportare le modifiche fondamentali al codice.
Ingegneria : alternativa intelligente alla droga.

Avatar utente
Foto Utentelellus
10 4
New entry
New entry
Messaggi: 57
Iscritto il: 27 ott 2013, 15:36
0
voti

[26] Re: Posizione librerie Visual C++

Messaggioda Foto Utentelellus » 1 mag 2016, 10:49

Grazie delle risposte. Facevo l'errore banale di scrivere 'r' invece di "r". Ho corretto e compila ma genera la seguente eccezione che non riesco a capire da dove possa provenire:

Eccezione non gestita di tipo 'System.AccessViolationException' in SimulazioneASPC.exe

Informazioni aggiuntive: Tentativo di lettura o scrittura della memoria protetta. Spesso questa condizione indica che altre parti della memoria sono danneggiate.

Lo stesso errore lo dava con la strcat nel seguente codice:

Codice: Seleziona tutto

 FileNames[FT_INI]                   = FNAME_INIT;
   sprintf(FileNames[FT_Rescue], "%s%s", RESCUE_OUT_DIR, RESCUE_FNAME);
    sprintf(FileNames[FT_QuantLawMsg], "%s%s", QUANT_OUT_DIR, QUANT_MSG_FNAME);
    sprintf(FileNames[FT_QuantLawSig], "%s%s", QUANT_OUT_DIR, QUANT_SIG_FNAME);
    sprintf(FileNames[FT_HDec], "%s%s", HDEC_OUT_DIR, HDEC_FNAME);
    sprintf(FileNames[FT_RndState_Source], "%s%s", RANDSTATE_OUT_DIR, RNS_SOURCE_FNAME);
    sprintf(FileNames[FT_RndState_Channel], "%s%s", RANDSTATE_OUT_DIR, RNS_CHANNEL_FNAME);
    sprintf(FileNames[FT_RndState_Puncturer], "%s%s", RANDSTATE_OUT_DIR, RNS_PUNCTURER_FNAME);

   /*
    FileNames[FT_Rescue]                = strcat(RESCUE_OUT_DIR, RESCUE_FNAME);
    FileNames[FT_QuantLawMsg]           = strcat(QUANT_OUT_DIR, QUANT_MSG_FNAME);
    FileNames[FT_QuantLawSig]           = strcat(QUANT_OUT_DIR, QUANT_SIG_FNAME);
    FileNames[FT_HDec]                  = strcat(HDEC_OUT_DIR, HDEC_FNAME);
    FileNames[FT_RndState_Source]       = strcat(RANDSTATE_OUT_DIR, RNS_SOURCE_FNAME);
    FileNames[FT_RndState_Channel]      = strcat(RANDSTATE_OUT_DIR, RNS_CHANNEL_FNAME);
    FileNames[FT_RndState_Puncturer]    = strcat(RANDSTATE_OUT_DIR, RNS_PUNCTURER_FNAME);
   */


Per quanto riguarda il codice qui sotto, sbaglio o dichiara una matrice in cui ogni riga punta ad un array di interi?

Codice: Seleziona tutto

fCodeLen      = CodeDimension[0];
   fCodeDim      = CodeDimension[1];
   fCodeRed      = fCodeLen - fCodeDim;

   Gmat = (int**) malloc (sizeof(int*)*fCodeDim); //array di puntatori ad intero

   for (i=0;i<fCodeDim;i++){
      Gmat[i] = (int*) malloc (sizeof(int)*fCodeLen);
      if (Gmat[i]==NULL){
         //printf("\n Error: No memory available for generator matrix to reduce in echelon form\n");
         exit(0);
      }
   }


Grazie ancora e scusate per le domande sicuramente banali.

Avatar utente
Foto Utentelellus
10 4
New entry
New entry
Messaggi: 57
Iscritto il: 27 ott 2013, 15:36
0
voti

[27] Re: Posizione librerie Visual C++

Messaggioda Foto Utentelellus » 1 mag 2016, 11:31

Come prima e molto sensata modifica vorrei far aprire il file all'interno del costruttore dato che c'è già una sua funzione interna che si occupa di chiuder il file dopo aver inizializzato la matrice. In parole povere dovrei quindi passare invece del file un parametro tipo : fSimPars->kvGmat.Value che contiene la stringa con il nome del file e poi all'interno scrivere:

Codice: Seleziona tutto

FILE *Gmatfile;

ecc...


Purtroppo mi è stato richiesto di usare i file handler e quindi vorrei rispettare tale richiesta. In questo caso come li dovrei usare?? Cioè dopo aver scritto FILE *Gmatfile come apro il file a partire dal valore passato alla funzione(cioè fSimPars->kvGmat ).


Torna a “Programmi applicativi: simulatori, CAD ed altro”