Мусор с указателями в классе, C++

Я использую Borland Builder C++. У меня утечка памяти, и я знаю, что это должно быть из-за созданного мной класса, но я не знаю, как это исправить. Пожалуйста, взгляните на мой код - мы будем благодарны за любые идеи!

Вот файл .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;

};

А вот и некоторые из файлов .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());

}  

Теперь, когда я использую класс в основном, я просто создаю указатель:

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

Где corners-> location - это строка из другого класса, а t [5] и t [6] - обе строки. Проблема в том, что imageLocation не содержит ожидаемого и часто представляет собой мусор. Я много читал об утечках памяти и указателях, но я все еще новичок в программировании, и некоторые из них довольно сбивают с толку. Любые предложения были бы потрясающими !!

Почему люди голосуют против этого? Мне кажется, что это законный вопрос. Я что-то упустил?

Onorio Catenacci 02.10.2008 21:17

Наверное, потому что это похоже на "пришлите, пожалуйста, код!" вопрос. Я думаю, что это правильный вопрос, но пример нужно очистить, чтобы нам не пришлось пробираться через 300 строк нерелевантного кода, чтобы помочь.

Outlaw Programmer 02.10.2008 21:25

Другая проблема - это терминология. Заголовок вопроса спрашивает об утечках памяти, но на самом деле это больше касается данных мусора.

matli 02.10.2008 21:30
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
1
3
1 281
6
Перейти к ответу Данный вопрос помечен как решенный

Ответы 6

У вас утечка памяти в main; вы создаете указатель с new, но не вызываете впоследствии delete.

Если вы хотите просто создать объект типа Header, который будет уничтожен при выходе из main, просто объявите его как «Header header;». Если вы хотите создать постоянный указатель, вы должны использовать new, как и вы, но обязательно delete header; и некоторые точка перед окончанием программы.

Ответ принят как подходящий

Боюсь, здесь есть ряд проблем.

Для начала, char ImageCordsRep[1]; не работает ... строка всегда заканчивается нулем, поэтому, когда вы выполняете strcpy(ImageCordsRep,"G");, вы переполняете буфер.

Также было бы неплохо завершить все эти строковые буферы нулевым значением в вашем конструкторе, чтобы они всегда были допустимыми строками.

Еще лучше было бы использовать класс строк вместо массивов символов или, по крайней мере, использовать strncpy для предотвращения переполнения буфера, если входящие строки больше, чем вы ожидаете.

Что-то другое...

Будьте осторожны, чтобы не использовать imageLocation после удаления объекта заголовка. Часто лучше скопировать строку из объекта, чем получать на него указатель. В этом случае все могло быть нормально, в зависимости от остальной части кода.

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

Ваша проблема в том, что ImageGeoLocation - это мусор или у вас утечка памяти?

Если ваш код написан как таковой:

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

Тогда ваша проблема не в утечке памяти, а в том, что вы удаляете память из-под imageLocation. ImageLocation - это просто указатель и на самом деле не содержит данных, он просто указывает на них. Итак, если вы удалите данные, указатель будет указывать на корзину.

Если это не так, отладьте свой метод SetHeader. Заполняется ли ImageGeoLocation данными, как вы ожидаете? Если это так, то imageLocation должен указывать на действительные данные, если не будет пропущенного кода, который впоследствии повредит ImageGeoLocation. Память о том, какое окно смотрит на ImageGeoLocation, может помочь, поскольку вы сможете пошагово просмотреть свой код и увидеть, какая строка на самом деле изменяет ImageGeoLocation там, где вы этого не ожидаете.

Спасибо, Торлак и другие за столь быстрый ответ. По сути, imageLocation заполняется нормально, если перед ним нет другого кода. Например, у меня есть этот список строк, который в основном содержит имена файлов.

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

Теперь, когда я пытаюсь сослаться на изображение из списка непосредственно перед ним, я получаю имя изображения, помещенного в imageLocation.

 //char * imageLocation = header->ImageGeoLocation; //as expected
Image1->Picture->LoadFromFile(imageNames->Strings[j]);
char * imageLocation = header->ImageGeoLocation; //puts name of jpg file in imageLocation

Я изменил strcpy() на strncpy(), и это решило мою проблему.

Другие вопросы по теме