▼프로그램 오류 증상
VC ++ 2013express에서 C ++ / CLI 를 사용하여 테트리스를 만들때
이미지 그리기 후에 메모리 해제가 이루어 지지 않아 메모리 사용량이 시작 시간에 비례하여 점점 늘어가고,
delete 키워드로 메모리 해제를 해도 전혀 개선의 여지가 보이지 않는다.
또한 Dispose 메서드를 호출하면 컴파일러에서 구성원 없다고 오류가 나옴.
이럴 경우 메모리 사용량 증가를 억제하는 방법은 무엇이 있고, 또한 있다면 왜 Dispose를 부를 수 없는가?
▼오류 발생 코드
// 렌더링 처리
// 배경 등은 30 × 30 이미지 집합체이므로 1 개로 후 화면에 그리기
void Tetris :: Render ( System :: Drawing :: Graphics ^ g, System :: Drawing :: Size ^ size ) {
using namespace System ;
using namespace System :: Drawing ;
// 이미지
Bitmap ^ tetrisImage = gcnew Bitmap ( "BackGroundImage.png" ) ;
// 합성 된 이미지
Bitmap ^ tetrisMap = gcnew Bitmap ( size - > Width, size - > Height ) ;
// 합성 Graphics 클래스
Graphics ^ tetrisGraphic = Graphics :: FromImage ( tetrisMap ) ;
// 배경을 붙여 용에 그려 넣는
for ( int y = 0 ; y < size - > Height ; y + = 30 ) {
for ( int x = 0 ; x < size - > Width ; x + = 30 ) {
tetrisGraphic - > DrawImage ( tetrisImage x, y, 30 , 30 ) ;
}
}
// 합성 된 이미지를 Form에 그려 컴
g - > DrawImage ( tetrisMap, 0 , 0 ) ;
// 보드 합성 전에 이미지
tetrisImage = gcnew Bitmap ( "BoardBackImage.png" ) ;
// 보드 합성 후 이미지
tetrisMap = gcnew Bitmap ( size - > Width, size - > Height ) ;
// 합성 쓰기 Graohics 클래스
tetrisGraphic = Graphics :: FromImage ( tetrisMap ) ;
// ColorMatrix 객체 생성
Imaging :: ColorMatrix ^ cm = gcnew Imaging :: ColorMatrix ( ) ;
// ColorMatrix 행렬의 값을 변경 하여 알파 값이 0.5으로 변경되도록 할
cm - > Matrix00 = 1 ;
cm - > Matrix11 = 1 ;
cm - > Matrix22 = 1 ;
cm - > Matrix33 = 0.5F ;
cm - > Matrix44 = 1 ;
// 이미지 메타 데이터 저장 클래스
Imaging :: ImageAttributes ^ ia = gcnew Imaging :: ImageAttributes ( ) ;
// 컬러 매트릭스를 지정
ia - > SetColorMatrix ( cm ) ;
// 합성 쓰기
for ( int y = 0 ; y < STAGE_HEIGHT ; y ++ ) {
for ( int x = 0 ; x < STAGE_WIDTH ; x ++ ) {
tetrisGraphic - > DrawImage ( tetrisImage, * new Drawing :: Rectangle ( 0 , 0 , STAGE_WIDTH * 30 , STAGE_HEIGHT * 30 ) , System :: Int32 ( x * 30 ) , System :: Int32 ( y * 30 ) , System :: Int32 ( 30 ) , System :: Int32 ( 30 ) , GraphicsUnit :: Pixel , ia ) ;
}
}
g - > DrawImage ( tetrisMap, 0 , 0 ) ;
// 블록 원본 이미지
tetrisImage = gcnew Bitmap ( "MoveBlock.png" ) ;
// 블록 이미지 (Form 붙여 넣기)
tetrisMap = gcnew Bitmap ( size - > Width, size - > Height ) ;
// 블록 합성 Graphics 클래스
tetrisGraphic = Graphics :: FromImage ( tetrisMap ) ;
// 블록 자르기 용 Rectangle 클래스
Drawing :: Rectangle ^ rect = gcnew Drawing :: Rectangle ( 0 , 0 , 29 , 29 ) ;
// 각 색상의 블록을 가진 BitMap 배열
array < Bitmap ^ > ^ blocks = gcnew array < Bitmap ^ > ( 10 ) ;
// 블록을 배열에 저장
for ( int I = 0 ; i < 7 ; i ++ ) {
blocks [ i ] = tetrisImage - > Clone ( * rect, tetrisImage - > PixelFormat ) ;
rect - > Location. X + = 30 ;
rect - > Location. Y + = 30 ;
}
// 블록을 붙여 위해 그려 넣는
for ( int y = 0 ; y < STAGE_HEIGHT ; y ++ ) {
for ( int x = 0 ; x < STAGE_WIDTH ; x ++ ) {
if ( board. getBoardStatus ( x, y ) == Box ) {
tetrisGraphic - > DrawImage ( blocks [ block. getMoveBlockType ( ) ] , x * 30 , y * 30 , 30 , 30 ) ;
}
}
}
// 합성 된 이미지를 Form에 그려 넣는
g - > DrawImage ( tetrisMap, 0 , 0 ) ;
// 메모리 해제
delete tetrisGraphic ;
delete tetrisImage ;
delete tetrisMap ;
}
프로그램 오류 해결 방법1
delete 의한 소멸자 (Dispose 메소드)의 호출은 3 번째 자원에는 적용되지 않았다.
/ 렌더링 처리
// 배경 등은 30 × 30 이미지 집합체이므로 1 개로 후 화면에 그리기
void Tetris :: Render ( System :: Drawing :: Graphics ^ g, System :: Drawing :: Size ^ size ) {
// 이미지
Bitmap ^ tetrisImage = gcnew Bitmap ( "BackGroundImage.png" ) ;
// 합성 된 이미지
Bitmap ^ tetrisMap = gcnew Bitmap ( size - > Width, size - > Height ) ;
// 합성 Graphics 클래스
Graphics ^ tetrisGraphic = Graphics :: FromImage ( tetrisMap ) ;
... // 보드 합성 전에 이미지 tetrisImage = gcnew Bitmap ( "BoardBackImage.png" ) ; // 보드 합성 후 이미지
프로그램 오류 해결 방법2
Dispose가 필요없는 것은 delete를하지 않는 편이 낫다.
C ++ / CLI는 gcnew 이외에도 ^을 지정하지 않고 변수 선언을 하면 인스턴스가 가능하므로, 국소 변수함으로써 소멸자를 호출 할 수 있다. 예를 들어
아래의 코드를
// 보드 합성 전에 이미지
tetrisImage = gcnew Bitmap ( "BoardBackImage.png" ) ;
// 보드 합성 후 이미지
tetrisMap = gcnew Bitmap ( size - > Width, size - > Height ) ;
// 합성 쓰기 Graohics 클래스
tetrisGraphic = Graphics :: FromImage ( tetrisMap ) ;
// ColorMatrix 객체 생성
Imaging :: ColorMatrix ^ cm = gcnew Imaging :: ColorMatrix ( ) ;
// ColorMatrix 행렬의 값을 변경하여 알파 값이 0.5로 변경되도록 할
cm - > Matrix00 = 1 ;
cm - > Matrix11 = 1 ;
cm - > Matrix22 = 1 ;
cm - > Matrix33 = 0.5F ;
cm - > Matrix44 = 1 ;
// 이미지 메타 데이터 저장 클래스
Imaging :: ImageAttributes ^ ia = gcnew Imaging :: ImageAttributes ( ) ;
// 컬러 매트릭스를 지정
ia - > SetColorMatrix ( cm ) ;
// 쓰기
// 메모리 해제
delete tetrisGraphic ;
delete tetrisImage ;
delete tetrisMap ;
delete ia ;
tetrisGraphic = nullptr ;
tetrisImage = nullptr ;
tetrisMap = nullptr ;
ia = nullptr ;
아래 처럼
{
// 보드 합성 전에 이미지
Bitmap tetrisImage ( "BoardBackImage.png" ) ;
// 보드 합성 후 이미지
Bitmap tetrisMap ( size - > Width, size - > Height ) ;
// 합성 쓰기 Graohics 클래스
Graphics ^ tetrisGraphic = Graphics : : FromImage ( & tetrisMap ) ; // 여기는 ^ 밖에 받을 수 없기 때문에 delete하는
// ColorMatrix 객체 생성
Imaging :: ColorMatrix cm ;
// ColorMatrix 행렬의 값을 변경하여 알파 값이 0.5로 변경 되도록 할
cm. Matrix00 = 1 ;
cm. Matrix11 = 1 ;
cm. Matrix22 = 1 ;
cm. Matrix33 = 0.5F ;
cm. Matrix44 = 1 ;
// 이미지 메타 데이터 저장 클래스
Imaging :: ImageAttributes ia ;
/ / 컬러 매트릭스를 지정
ia. SetColorMatrix ( cm ) ;
// 쓰기
// 메모리 해제
delete tetrisGraphic ;
tetrisGraphic = nullptr ;
}
# C #의 using 같은 이미지로 사용할 수있다.
아래의 코드 >> Graphics ^ tetrisGraphic =
Graphics :: FromImage (& tetrisMap); // 여기는 ^ 밖에 받을 수 없기 때문에 delete하기 Graphics ^ tetrisGraphic =
Graphics :: FromImage (% tetrisMap); // 여기는 ^ 이 밖에 받지 않기 때문에 delete하기 >> ia.SetColorMatrix (cm); 는 ia.SetColorMatrix (% cm);