Visualizzazione dei risultati da 1 a 6 su 6
  1. #1

    [C++] Invocazione costruttore a posteriori

    Salve a tutti sto scrivendo un programma di decodifica dei file JPEG. Per far questo ho creato una classe che si dedica alla scansione del file alla ricerca dei marker e ad ogni marker trovato crea sul momento l'istanza di una nuova classe dedicata alla sua interpretazione.

    lo pseudo codice è circa questo:
    codice:
    // Classe ScanHeader
    
    fstream in("file.jpg", ios::in | ios::binary);
    while(!eof){
      WORD marker = in.leggiMarker();
      switch(marker){
          case M1:
             {
               // Chiamo la classe M1 che gestisce i marker di tipo M1 col costruttore
                M1 emme1(in);
              }
               break;
          case M2:
             {
               // Chiamo la classe M2 che gestisce i marker di tipo M2 col costruttore
                M2 emme2(in);
              }
               break;
    etc...
      }
    
    
    }
    Il problema è che la classe ScanHeader che fa questo lavoro ha bisogno di alcuni dati delle classi che sono invocate man mano, che in questo caso verrebbero distrutte perché istanziate dentro lo switch case. Allora ho messo come variabili della classe ScanHeader le classi di cui mi servono i dati (M1, M2 etc), e poi provo a fare una copia ma i risultati sono un SIGSEV.

    Sarebbe inoltre più comodo per me se riuscissi a invocare il costruttore di queste classi (che ha bisogno di un filestream con la testina settata nel punto giusto, cioè nello switch case e non prima) ma una cosa del tipo
    codice:
    nel file ScanHeader.hpp:
    M1 emme1;
    nel file ScanHeader.cpp:
    case M1:
    emme1(in);
    non funziona.
    Ho provato infine a mettere nella definizione di ScanHeader solo un dato, e poi a copiare solo quello dentro, ma ottengo sempre SIGSEV.

    Spero di essere stato chiaro e chiedo il vostro aiuto oramai sono senza idee

  2. #2
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Non c'entra niente il costruttore qui. Le variabili sono sullo stack e fuori dallo switch case vengono sempre distrutte. Se vuoi farle sopravvivere le devi allocare dinamicamente con new e se le due classi derivano da una classe comune, meglio ancora. I puntatori li devi mettere fuori dallo switch case altrimenti hai memory leak e non risolvi niente.

    Come sono definite le due classi M1 e M2?
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  3. #3
    Posto il codice vero.
    Uno dei marker si chiama DHT (Define Huffman Table).
    Contiene una struttura dati che serve alla classe principale che si chiama JpegHeader.

    Ecco la definizione di DHT:
    codice:
    class Dht {
    public:
        Dht();
        Dht(fstream &fs);
        int Extract(fstream &in);
        void printBinaryCodes();
        void printData();
        vector<HuffmanTable> huffmanTables;
    };
    La funzione Extract elabora il filestream dentro al costruttore e inizializza il vettore huffmanTables. Le altre funzioni stampano dati utili.

    HuffmanTable è una struttura dati così definita:
    codice:
    typedef struct ht {
        unsigned char valuesPerLength[16];
        unsigned char* values;
        unsigned short int* codes;
        unsigned char Tc;
        unsigned char Th;
    
    } HuffmanTable;
    values e codes sono array di interi dinamicamente allocati al momento della costruzione tramite malloc.

    Alla classe JpegHeader serve che sopravviva l'istanza di Dht perchè gli serve il vettore huffmanTables per elaborazioni successive.

    Il costruttore di Dht da me definito prende per reference un fstream con la testina già posizionata ad un certo punto e inizializza il vettore huffmanTables.

    Dentro la classe JpegHeader c'è il famoso switch case di cui il case d'interesse è il seguente:
    codice:
     switch ((b & 0x0F)) {
                            // DHT
                        case 0x04:
                        {
                            cout << "Trovata la tabella di Huffman" << endl;
    
                            Dht eh(file);
                            tabelle = eh.huffmanTables;
    file è l'fstream, eh è l'istanza temporanea, tabelle sarebbe un vettore di JpegHeader.
    Ho provato inoltre a fare:
    codice:
    tabelle = new Dht(file);
    con tabelle dichiarato come puntatore a Dht e anche a fare
    codice:
    Dht eh(file);
    tabelle = eh;
    con tabelle dichiarato come dato Dht

    Il problema è del tutto analogo con altre classi deputate a interpretare altri marker.

  4. #4
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    Originariamente inviato da searunner
    Alla classe JpegHeader serve che sopravviva l'istanza di Dht perchè gli serve il vettore huffmanTables per elaborazioni successive.
    codice:
    DHT* tabelle = nullptr; // o NULL se il compilatore non supporta ancora C++x11 
     switch ((b & 0x0F)) {
                            // DHT
                        case 0x04:
                        {
                            cout << "Trovata la tabella di Huffman" << endl;
    
                            tabelle = new Dht eh(file);
    Così l'istanza di DHT sopravvive, però dovresti controllare se all'interno del costruttore ci sono problemi con la memoria. Per inciso l'invocazione posticipata del costruttore è possibile ma:
    1) passa sempre attraverso un'allocazione di memoria;
    2) si fa solo in casi particolari;
    3) se il costruttore è "bacato", il problema non lo risolvi.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

  5. #5
    eh il problema è che con quel codice mi va in segmentation fault, provo a rivedere dove ho sbagliato
    Altra domanda non direttamente collegata:
    nelle varie classi dove gestisco gli header, dove non so a priori la dimensione del dato uso puntatori che alloco con malloc. Se la classe che li contiene muore, quella memoria si libera da sola oppure devo definire un distruttore di default che faccia delle free su questi dati?

  6. #6
    Utente di HTML.it L'avatar di shodan
    Registrato dal
    Jun 2001
    Messaggi
    2,381
    La devi liberare tu: il C++ non lo fa al posto tuo.
    Per evitare il problema e meglio usare gli shared_ptr.
    This code and information is provided "as is" without warranty of any kind, either expressed
    or implied, including but not limited to the implied warranties of merchantability and/or
    fitness for a particular purpose.

Permessi di invio

  • Non puoi inserire discussioni
  • Non puoi inserire repliche
  • Non puoi inserire allegati
  • Non puoi modificare i tuoi messaggi
  •  
Powered by vBulletin® Version 4.2.1
Copyright © 2024 vBulletin Solutions, Inc. All rights reserved.