Pregunta

Estoy usando Borland Builder C ++. Tengo una pérdida de memoria y sé que debe ser debido a esta clase que creé, pero no estoy seguro de cómo solucionarlo. Por favor mire mi código: ¡cualquier idea sería muy apreciada!

Aquí está el archivo .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;

};

Y aquí está algo del archivo .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());

}  

Ahora cuando uso la clase main, básicamente creo un puntero:

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

Donde corners - > location es una cadena de otra clase, y t [5] yt [6] son ??ambas cadenas. El problema es que imageLocation no contiene lo que se espera y, a menudo, solo basura. He leído mucho acerca de las fugas de memoria y los indicadores, pero todavía soy muy nuevo en programación y parte de eso es bastante confuso. ¡Cualquier sugerencia sería fabulosa!

¿Fue útil?

Solución

Me temo que hay varios problemas aquí.

Para los arrancadores char ImageCordsRep [1]; no funciona ... una cadena siempre termina en nulo, así que cuando haces strcpy (ImageCordsRep, " G "); está desbordando el búfer.

También sería una buena práctica terminar todos esos búferes de cadena con un nulo en su constructor, por lo que siempre son cadenas válidas.

Incluso mejor sería usar una clase de cadena en lugar de los arrays de caracteres, o al menos usar 'strncpy' para evitar sobrecargas de búfer si las cadenas entrantes son más grandes de lo que esperas.

Otros consejos

Su pérdida de memoria está en main ; está haciendo un puntero con new , pero no está llamando posteriormente a delete .

Si solo desea crear un objeto de tipo Header que se destruirá cuando main salga, simplemente declare que es " Encabezado de cabecera; " Si desea crear un puntero persistente, debe usar new como lo hace, pero asegúrese de eliminar el encabezado; y algún punto antes de que finalice el programa.

¿Está su problema de que ImageGeoLocation es basura o tiene una pérdida de memoria?

Si el código está escrito como tal:

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

Entonces, el problema no es una pérdida de memoria, sino que está eliminando la memoria de debajo de imageLocation. ImageLocation es solo un puntero y en realidad no contiene datos, solo apunta a ellos. Por lo tanto, si elimina los datos, el puntero está apuntando a la papelera.

Si ese no es el caso, entonces depure su método SetHeader. ¿Se está llenando ImageGeoLocation con los datos como espera? Si es así, entonces imageLocation debe apuntar a datos válidos a menos que haya algún código omitido que esté dañando ImageGeoLocation más adelante. Una memoria que la ventana de visualización de ImageGeoLocation puede ayudar, ya que podrá recorrer su código y ver qué línea cambia realmente a ImageGeoLocation donde no lo espera.

Cambié strcpy () a strncpy () y resolví mi problema.

Algo más ...

Tenga cuidado de no usar imageLocation después de eliminar el objeto del encabezado. A menudo es mejor copiar la cadena del objeto en lugar de apuntarle un puntero. Podría estar bien en este caso dependiendo del resto del código.

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

Gracias, Torlack y otros por responder tan rápido. Básicamente, imageLocation se llena bien, a menos que tenga otro código antes. Por ejemplo, tengo esta lista de cadenas, que básicamente contiene nombres de archivos.

    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);

Ahora, cuando trato de referirme a una imagen de la lista directamente antes, me pongo el nombre de la imagen dentro de imageLocation.

 //char * imageLocation = header->ImageGeoLocation; //as expected
Image1->Picture->LoadFromFile(imageNames->Strings[j]);
char * imageLocation = header->ImageGeoLocation; //puts name of jpg file in imageLocation
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top