Я использую 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 не содержит ожидаемого и часто представляет собой мусор. Я много читал об утечках памяти и указателях, но я все еще новичок в программировании, и некоторые из них довольно сбивают с толку. Любые предложения были бы потрясающими !!
Наверное, потому что это похоже на "пришлите, пожалуйста, код!" вопрос. Я думаю, что это правильный вопрос, но пример нужно очистить, чтобы нам не пришлось пробираться через 300 строк нерелевантного кода, чтобы помочь.
Другая проблема - это терминология. Заголовок вопроса спрашивает об утечках памяти, но на самом деле это больше касается данных мусора.





У вас утечка памяти в 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(), и это решило мою проблему.
Почему люди голосуют против этого? Мне кажется, что это законный вопрос. Я что-то упустил?