2008-10-02 86 views
-1

我正在使用Borland Builder C++。我有一個內存泄漏,我知道它必須是因爲我創建的這個類,但我不知道如何解決它。請看我的代碼 - 任何想法將不勝感激!類中的指針垃圾,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; 

其中corner-> location是來自另一個類的字符串,t [5]和t [6]都是字符串。問題是imageLocation不包含所期望的內容,而且通常只是垃圾。我已經閱讀了很多關於內存泄漏和指針的問題,但是我對編程還是很陌生的,而且其中一些非常混亂。任何建議將是神話般的!

+0

爲什麼人們低估了這一點?對我來說這似乎是一個合法的問題。我在這裏錯過了什麼嗎? – 2008-10-02 17:17:54

回答

5

恐怕這裏有很多問題。

對於初學者char ImageCordsRep[1];不起作用...一個字符串總是空終止,所以當你做strcpy(ImageCordsRep,"G");時,你正在溢出緩衝區。

在您的構造函數中使用null終止所有這些字符串緩衝區也是一個好習慣,因此它們總是有效的字符串。

更好的辦法是使用一個字符串類而不是char數組,或者至少使用'strncpy'來防止緩衝區溢出,如果傳入的字符串比您期望的大。

2

您的內存泄漏位於main;您正在製作一個帶有new的指針,但不會隨後調用delete

如果你希望只創建Header類型將被銷燬時main退出,只是聲明爲「Header header;」如果你想創建一個持久的指針,你做你應該使用new,但可以肯定的對象到delete header;和程序結束之前的某個點。

0

別的東西......

要小心,不要使用imageLocation頭對象被刪除之後。從對象中複製字符串通常會更好,而不是獲取指向它的指針。根據代碼的其餘部分,在這種情況下可以確定。

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

是你的問題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,這是你不期望的。

0

謝謝你,托拉克和其他人的回覆如此之快。基本上,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 
1

因此,我將strcpy()更改爲strncpy(),它擺脫了垃圾!謝謝大家!