Domanda

Sto usando Borland Builder C ++. Ho una perdita di memoria e so che deve essere a causa di questa classe che ho creato, ma non sono sicuro di come risolverlo. Per favore, guarda il mio codice: qualsiasi idea sarebbe molto apprezzata!

Ecco il file .h:

#ifndef HeaderH
#define HeaderH
#include <vcl.h>
#include <string>
using std::string;
class Header {

 public:
    //File Header
    char FileTitle[31];
    char OriginatorName[16];

    //Image Header
    char ImageDateTime[15];
    char ImageCordsRep[2];
    char ImageGeoLocation[61];

    NitfHeader(double latitude, double longitude, double altitude, double heading);
    ~NitfHeader();
    void SetHeader(char * date, char * time, double location[4][2]);  


 private:

    void ConvertToDegMinSec (double angle, AnsiString & s, bool IsLongitude);
    AnsiString ImageDate;
    AnsiString ImageTime;
    AnsiString Latitude_d;
    AnsiString Longitude_d;
    double Latitude;
    double Longitude;
    double Heading;
    double Altitude;

};

Ed ecco alcuni dei file .cpp:

void Header::SetHeader(char * date, char * time, double location[4][2]){
    //File Header
strcpy(FileTitle,"Cannon Powershot A640");
strcpy(OperatorName,"Camera Operator");

   //Image Header
//Image Date and Time
   ImageDate = AnsiString(date);
   ImageTime = AnsiString(time);
   AnsiString secstr = AnsiString(ImageTime.SubString(7,2));
   AnsiString rounder = AnsiString(ImageDate.SubString(10,1));
   int seconds = secstr.ToInt();
    //Round off seconds  - will this be necessary with format hh:mm:ss in text file?
   if (rounder.ToInt() > 4) {
     seconds++;
    }
   AnsiString dateTime = ImageDate.SubString(7,4)+ ImageDate.SubString(4,2) + ImageDate.SubString(1,2) + ImageTime.SubString(1,2)
                    + ImageTime.SubString(4,2) + AnsiString(seconds);
   strcpy(ImageDateTime,dateTime.c_str());

   //Image Coordinates Representation
   strcpy(ImageCordsRep,"G");

   //Image Geographic Location
   AnsiString lat;
   AnsiString lon;
   AnsiString locationlat_d;
   AnsiString locationlon_d;
   AnsiString corner;

   for (int i = 0; i < 4; i++){

     ConvertToDegMinSec(location[i][0],lat,false);
     ConvertToDegMinSec(location[i][1],lon,true);

     if(location[i][0] < 0){
        locationlat_d = 'S';
        ConvertToDegMinSec(-location[i][0],lat,false);
      }else if(location[i][0] > 0){
        locationlat_d = 'N';
     }else locationlat_d = ' ';

     if(location[i][1] < 0){
        locationlon_d = 'W';
        ConvertToDegMinSec(-location[i][1],lon,true);
     }else if(location[i][1] > 0){
         locationlon_d = 'E';
     }else locationlon_d = ' ';

     corner += lat + locationlat_d + lon + locationlon_d;

   }
   strcpy(ImageGeoLocation,corner.c_str());

}  

Ora quando uso la classe in main, fondamentalmente creo solo un puntatore:

Header * header = new Header;
header->SetHeader(t[5],t[6],corners->location);
char * imageLocation = header->ImageGeoLocation;
//do something with imageLocation
delete header;

Dove corner- > location è una stringa di un'altra classe e t [5] et t [6] sono entrambe stringhe. Il problema è che imageLocation non contiene ciò che è previsto, e spesso solo spazzatura. Ho letto molto su perdite di memoria e puntatori, ma sono ancora molto nuovo nella programmazione e alcuni sono piuttosto confusi. Qualsiasi suggerimento sarebbe favoloso !!

È stato utile?

Soluzione

Temo che ci siano una serie di problemi qui.

Per cominciare char ImageCordsRep [1]; non funziona ... una stringa ha sempre una terminazione nulla, quindi quando si esegue strcpy (ImageCordsRep, " G "); stai sovraccaricando il buffer.

Sarebbe anche buona norma terminare tutti quei buffer di stringhe con un null nel costruttore, quindi sono sempre stringhe valide.

Ancora meglio sarebbe usare una classe di stringhe invece degli array di caratteri, o almeno usare 'strncpy' per prevenire sovraccarichi del buffer se le stringhe in arrivo sono più grandi di quanto ti aspetti.

Altri suggerimenti

La perdita di memoria è in main ; stai facendo un puntatore con nuovo , ma non successivamente chiamando elimina .

Se desideri solo creare un oggetto di tipo Header che verrà distrutto alla chiusura di main , dichiaralo come " Header header; " Se desideri creare un puntatore persistente, dovresti usare new , ma assicurati di eliminare l'intestazione; e qualche punto prima della fine del programma.

Il tuo problema è che ImageGeoLocation è un cestino o hai una perdita di memoria?

Se il tuo codice è scritto come tale:

Header * header = new Header;
header->SetHeader(t[5],t[6],corners->location);
char * imageLocation = header->ImageGeoLocation;
delete header;
printf("ImageLocation is %s", imageLocation);

Quindi il tuo problema non è una perdita di memoria, ma stai eliminando la memoria da imageLocation. ImageLocation è solo un puntatore e in realtà non contiene dati, ma solo punti ad esso. Quindi, se elimini i dati, il puntatore punta al cestino.

In caso contrario, eseguire il debug del metodo SetHeader. ImageGeoLocation viene popolato di dati come previsto? In tal caso, imageLocation deve puntare a dati validi a meno che non vi sia un codice omesso che danneggi ImageGeoLocation in un secondo momento. Un ricordo di ciò che la finestra che osserva ImageGeoLocation può aiutare poiché sarai in grado di scorrere il tuo codice e vedere quale riga cambia effettivamente ImageGeoLocation dove non ti aspetti.

Ho cambiato strcpy () in strncpy () e ho risolto il mio problema.

Qualcos'altro ...

Fai attenzione a non usare imageLocation dopo aver eliminato l'oggetto header. Spesso è meglio copiare la stringa dall'oggetto invece di ottenere un puntatore ad esso. Potrebbe essere OK in questo caso a seconda del resto del codice.

Header * header = new Header;
header->SetHeader(t[5],t[6],corners->location);
char * imageLocation = header->ImageGeoLocation;

Grazie, Torlack e altri per aver risposto così rapidamente. Fondamentalmente, imageLocation viene popolato bene, a meno che non abbia altro codice prima di esso. Ad esempio, ho questo elenco di stringhe, che in pratica contiene nomi di file.

    AnsiString fileType ("*.jpg");
    AnsiString path = f + fileType;
    WIN32_FIND_DATA fd;
    HANDLE hFindJpg = FindFirstFile(path.c_str(),&fd);

   //Find all images in folder
    TStringList * imageNames = new TStringList;

    if (hFindJpg != INVALID_HANDLE_VALUE) {
        do{

            if(!(fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)){
                image = AnsiString(fd.cFileName);
                imageNames->Add(image);

                jpgFileCount++;
            }

        }while(FindNextFile(hFindJpg,&fd));
    }else ShowMessage ("Cannot find images.");

    FindClose(hFindJpg);

Ora quando provo a fare riferimento a un'immagine dall'elenco direttamente prima, ottengo il nome dell'immagine inserito in imageLocation.

 //char * imageLocation = header->ImageGeoLocation; //as expected
Image1->Picture->LoadFromFile(imageNames->Strings[j]);
char * imageLocation = header->ImageGeoLocation; //puts name of jpg file in imageLocation
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top