سؤال

وأستخدمه بورلاند باني C ++. لدي تسرب الذاكرة وأنا أعلم أنه يجب أن يكون لهذه الفئة أنا خلقت، لكنني لست متأكدا من كيفية إصلاحه. يرجى النظر في بلدي code-- أي أفكار سيكون موضع تقدير كبير!

إليك الملف .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());

}  

والآن عندما تستخدم فئة في main، أساسا أنا فقط إنشاء مؤشر:

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

وأين corners-> الموقع سلسلة من فئة أخرى، ور [5] و t [6] على حد سواء السلاسل. والمشكلة هي أن imageLocation لا يحتوي على ما هو متوقع، وكثير من الأحيان مجرد القمامة. لقد قرأت الكثير عن تسرب الذاكرة والمؤشرات، لكنني ما زلت جديدة جدا لبرمجة وبعض من هو مربكا للغاية. ان اي اقتراحات يكون رائع !!

هل كانت مفيدة؟

المحلول

وأخشى أن هناك عددا من القضايا هنا.

وبالنسبة للمبتدئين char ImageCordsRep[1]; لا يعمل ... هو دائما فارغة إنهاء سلسلة، وذلك عند قيام strcpy(ImageCordsRep,"G"); كنت تفيض المخزن المؤقت.

وسيكون أيضا أن تكون ممارسة جيدة لإنهاء كل تلك المخازن سلسلة مع فارغة في المنشئ الخاص بك، لذلك هم دائما سلاسل صالحة.

وأفضل حتى يكون استخدام فئة سلسلة بدلا من صفائف شار، أو على الأقل استخدام "strncpy" لمنع التجاوزات عازلة إذا كان الجمل الواردة أكبر مما كنت تتوقع.

نصائح أخرى

وتسرب الذاكرة الخاص بك هو في main. كنت ترغب بجعل المؤشر مع new، ولكن ليس في وقت لاحق يدعو delete.

إذا كنت ترغب في مجرد إنشاء كائن من نوع Header التي سيتم تدميرها عند مخارج main، فقط نعلن على أنها "Header header;" إذا كنت ترغب في إنشاء مؤشر المستمر، يجب عليك استخدام new كما كنت تفعل، ولكن يجب التأكد من delete header; ومرحلة ما قبل انتهاء البرنامج.

هل مشكلتك أن 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 في وقت لاحق. A الذاكرة ما النافذة تبحث في ImageGeoLocation يمكن أن تساعد وبما انك ستكون قادرا على التنقل خلال التعليمات البرمجية الخاصة بك ومعرفة أي خط يغير في الواقع ImageGeoLocation حيث لا تتوقع.

ولقد غيرت strcpy() إلى strncpy() وأنها تحل مشكلتي.

وشيء آخر ...

ويجب الحرص على عدم استخدام imageLocation بعد حذف الكائن الرأس. انها في كثير من الأحيان أفضل لنسخ سلسلة من الكائن بدلا من الحصول على مؤشر إلى ذلك. ويمكن أن تكون على ما يرام في هذه الحالة اعتمادا على ما تبقى من التعليمات البرمجية.

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

وشكرا لكم، Torlack، وغيرها للرد بسرعة. في الأساس، ويحصل على 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
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top