2013-12-24 5 views
1

C++에서 메모리 누출 문제를 해결하려고하는데 비교적 C++에 익숙하지 않은 것 같습니다. 어리석은 일입니다. 나는 화면 캡쳐를하는 코드를 가지고 있으며, 그때 내가 조작 할 이미지를위한 메모리를 할당하고있다. 여기에 몇 가지 관련 코드는 다음과 같습니다메모리가 해제되지 않는 이유는 무엇입니까?

RGBTRIPLE* ScreenShot(char *BmpName, DWORD &height, DWORD &width, char* bmpToFree){ 
    DWORD FileSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+(sizeof(RGBTRIPLE)+1 * (Width*Height * 4)); 
    char *BmpFileData = (char*)GlobalAlloc(0x0040, FileSize); 

    // Some code 

    BitBlt(CaptureDC, 0, 0, Width, Height, DevC, 0, 0, SRCCOPY | CAPTUREBLT); 
    GetDIBits(CaptureDC, CaptureBitmap, 0, Height, Image, (LPBITMAPINFO)BInfoHeader, DIB_RGB_COLORS); 

    height = Height; 
    width = Width; 
    bmpToFree = BmpFileData; 

    DeleteObject(CaptureBitmap); 
    DeleteObject(CaptureDC); 
} 

난 아직도 내가이 줄 또 다른 포인터 포인터를 통과하는 참조를 유지하므로 다른 방법이 데이터로 작업해야하기 때문에 당신은 내가 GlobalFree(BmpFileData)와 BmpFileData을 확보하고 있지 않다 볼 수 있듯이 bmpToFree = BmpFileData;

그래서 지금은이 데이터에 어떤 일을하고 나는이 길에 GlobalFree()를 사용

char* bmpToFree = NULL; 

RGBTRIPLE *image = ScreenShot("Prueba.bmp", h, w, bmpToFree); 
// Do some work 
GlobalFree(bmpToFree); 

을하지만이 방법에 난 메모리 누수를있다. 대신 GlobalFree(BmpFileData)Screenshot() 메서드 안에 넣으면 내 누출은 없어지지 만 작업 할 데이터가 없습니다.

내가 뭘 잘못하고 있니?

+1

메모리 누수가 있음을 어떻게 알 수 있습니까? – Floris

+0

몇 분 안에 프로그램을 시작하면 거의 모든 8Gb RAM을 사용합니다 – Andres

답변

5

문제는 bmpToFree이 포인터에 대한 참조 여야한다는 것입니다.

RGBTRIPLE* ScreenShot(.., char* bmpToFree) 

RGBTRIPLE* ScreenShot(.., char* &bmpToFree) 

해야 또는 다른 방법으로 그것을 밖으로 작업 할 수 있습니다.

RGBTRIPLE* ScreenShot(.., char** bmpToFree) 
{ 
    ... 
    *bmpToFree = BmpFileData; 
} 

그들은 기본적 변수 (char *) 참조 (&) 또는 가변 (char *) 포인터 (*) 중 어느 하나와 동일하다. 복사본 대신 전달 된 원래 변수를 변경해야 할 때이를 사용합니다.

+0

그냥 ... 와우, 너무 간단! 그 차이점은 무엇입니까? 참조는 포인터와 같지만 포인터는 무엇인지 가리킬 수 없습니다. 절대 포인터에 대한 언급을 듣지 못했습니다! – Andres

+0

참조는 본질적으로 내부적으로 변수에 대한 포인터입니다. 값으로 복사 대신 참조로 복사합니다. 참조를 변경하면 복사본 대신 원본 개체가 변경됩니다. 귀하의 경우에는, 나중에 무료로 사용하려는 주소를 저장하는 포인터 자체가되는 외부 변수를 변경해야합니다. –

2

포인터 값을 함수에 전달하고 있지만 반환하면 원래 값은 업데이트되지 않습니다. 기능

bmpToFree = BmpFileData; 

내부의 문이 실제로 호출 루틴에서 변수를 갱신하도록 - 당신은 포인터에 대한 참조를 전달해야합니다. 당신이 당신이 기대하는 함수 서명을 변경해야 할이 일을하려면

&bmpToFree 

이며, 포인터의 주소를 전달하여이 작업을 수행 할 수있는 포인터 - 투 - 어 - 포인터

RGBTRIPLE* RGBTRIPLE* ScreenShot(char *BmpName, DWORD &height, DWORD &width, char** bmpToFree); 

inside the function, you change the line to 

*bmpToFree = BmpFileData; 

그리고 당신은 그것을 호출

RGBTRIPLE *image = ScreenShot("Prueba.bmp", h, w, &bmpToFree); 
2

최대한 멀리 볼 수있는, 기능이 같은 선언해야합니다

RGBTRIPLE* ScreenShot(char *BmpName, DWORD &height, DWORD &width, char*& bmpToFree) 

포인터를 지정하면 포인터는 bmpToFree의 로컬 복사본에 해당하며 함수가 반환 된 후에도 남아 있지 않습니다.

1

함수에서 인수를 수정하려면 해당 인수를 값이 아닌 참조로 전달해야합니다. 포인터 또는 참조를 사용할 수 있지만 참조가 바람직합니다.예를 들어

: (. 분명히 당신은 현실에서 반환 값을 사용하지만, 이것은 단지 예입니다)

void add(int a, int b, int& result) { 
    result = a + b; 
} 

또는

void add(int a, int b, int* result) { 
    *result = a + b; 
} 

NOT이 :

void add(int a, int b, int result) { 
    result = a + b; // Only local copy of result is modified 
} 

그래서, 귀하의 경우에는 포인터 인 인수의 값을 수정하려고합니다. 따라서이 인수는 참조로 전달해야합니다. char * & bmpToFree

관련 문제