[App 개발] Memory Leak 관련된 질문입니다.
본문
-(void) OnTimer
{
[self setNeedsDisplay];
}
-(void)drawRect:(CGRect)rect
{
if(!image2)
[image2 dealloc];
if(!imageView2)
{
[imageView2 dealloc];
}
const size_t width = scr_width;
const size_t height = scr_height;
const size_t bitsPerComponent = 8;
const size_t bitPerPixel = 32;
const size_t bytesPerRow = (bitPerPixel * width)/8;
CGBitmapInfo bi = kCGImageAlphaPremultipliedLast;
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(scrbuff, width, height, bitsPerComponent, bytesPerRow, cs, bi);
CGImageRef imageRef = CGBitmapContextCreateImage(context);
image2 = [UIImage imageWithCGImage:imageRef];
imageView2 = [[UIImageView alloc]initWithImage:image2];
imageView2.frame = CGRectMake(64, 0, scr_width, scr_height);
[self addSubview:imageView2];
free(&context);
free(&imageRef);
free(&cs);
}
이런 루틴이 있는데 메모리 릭이 발생합니다. imageView2를 할당하는 과정에서 메모리릭이 발생합니다.
mageView2 = [[UIImageView alloc]initWithImage:image2];
이부분 입니다.
그래서 다음과 같이 코드를 바꿨는데요
-(void)initImage
{
const size_t width = scr_width;
const size_t height = scr_height;
const size_t bitsPerComponent = 8;
const size_t bitPerPixel = 32;
const size_t bytesPerRow = (bitPerPixel * width)/8;
CGBitmapInfo bi = kCGImageAlphaPremultipliedLast;
CGColorSpaceRef cs = CGColorSpaceCreateDeviceRGB();
CGContextRef context = CGBitmapContextCreate(scrbuff, width, height, bitsPerComponent, bytesPerRow, cs, bi);
CGImageRef imageRef = CGBitmapContextCreateImage(context);
image2 = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGContextRelease(context);
CGColorSpaceRelease(cs);
free(&imageRef);
free(&context);
free(&cs);
}
static int a=0;
-(void)drawRect:(CGRect)rect
{
if(a==0){
[self initImage];
imageView2 = [[UIImageView alloc]initWithImage:image2];
[imageView2 setFrame:CGRectMake(64, 0, scr_width, scr_height)];
[self addSubview:imageView2];
a=1;
}
else {
[self initImage];
imageView2.image= image2;
[imageView2 setFrame:CGRectMake(64, 0, scr_width, scr_height)];
}
}
이렇게 했는데 메모리 릭은 발생을 안하는테 콘솔창에서 다음과 같은 에러가 뜹니다.
*** set a breakpoint in malloc_error_break to debug
cppCode(41769,0xa02ec500) malloc: *** error for object 0xbfffd2cc: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
cppCode(41769,0xa02ec500) malloc: *** error for object 0xbfffd2c4: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
cppCode(41769,0xa02ec500) malloc: *** error for object 0xbfffd2c8: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
cppCode(41769,0xa02ec500) malloc: *** error for object 0xbfffd2cc: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
cppCode(41769,0xa02ec500) malloc: *** error for object 0xbfffd2c4: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
cppCode(41769,0xa02ec500) malloc: *** error for object 0xbfffd2c8: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
cppCode(41769,0xa02ec500) malloc: *** error for object 0xbfffd2cc: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
cppCode(41769,0xa02ec500) malloc: *** error for object 0xbfffd2c4: pointer being freed was not allocated
이런 에러들이 뜹니다. 아직 상관이있는지 모르겠는데요.
질문입니다.
각자 객체들마다 할당과 해제가 너무 어려운것 같습니다. c/c++에서는 포인터인지만 확인하고 포인터면 지우면 ㄷㅚㅆ었는데요.
이건 객체가 할당되있다가 객체 안에 있는 포인터가 가리키는 변수안도 할당이 되어있는데 실수로 객체를 지우면 메모리 릭이
생기고.. 발생지점도 정확하게 디버깅으로 안나오고(제 실력문제인듯합니다.) 그 결과 코드가 두번째 처럼 불필요하게 꼬이고
전역변수를 선언하게 됩니다. 두번째 코드에서 UIImageView와 UIImage가 전역입니다. CG모듈과 UI붙은 이미지 관련 모듈쪽에서 이런일이 자주 발생하는데요 저의경우에 메모리 Leak를 피할수 있는 조언좀 부탁드립니다. 이거잡는데 하루를 꼴닥 보내서요.. 졸려서 말이 두서가 없습니다. 좋은하루되세요.
최신글이 없습니다.
최신글이 없습니다.
댓글목록 5
hongjuny님의 댓글
일단은 타이머에서 계속해서 화면 갱신을 요구하고 있으니 반복해서 drawRect 를 호출하고 있겠군요. image2 하고 imageView2 가 정확히 어디에 선언되어 있나요? 이 둘의 소재가 명확하지 않기 때문에 발생하는 문제 같군요. @property 로 retain 을 설정해 주시면 어떤가요?
박태원님의 댓글
제가 질문을 잘 파악했는지는 모르겠지만 기초적인 내용을 말씀드리자면
cocoa에서는 retain과 release로 관리됩니다.
alloc과 copy등은 내부에서 retain된다는 약속이 있기 때문에 alloc과 copy등의 메시지를 사용하시면 반드시 어디에선가 release/autorelease메시지가 발생되어야 합니다.
알고 계신 내용이실 수도 있지만 혹시나 해서 올립니다.
Kenny님의 댓글
어제 가입해서 이제야 봤네요.
기본적으로 reference counting에서는 결자해지 원칙만 지키면 간단합니다.
그러니까 alloc한 것은 언젠가는 release를 해 주셔야하고요. 통상적으로는 symmetric하게 하면 되요. init 때 만들면, dealloc 호출들어올 때 release해주고요...
제일 처음 코드에서, addSubview가 자기 인자로 받은 imageView2를 retain하기 때문에, 릭이 발생하는거에요.
통상적으로 객체를 만들어 어떤 집합 객체에 추가하는 형태는 다음과 같습니다.
Child *child = [[Child alloc] init]; // child의 refcount: 1
[parent addChild:child]; // child의 refcount: 2
[child release]; // refcount: 1
그리고 집합 객체는 자신에게서 child 하나를 제거할 때에 child를 release해 줍니다. 그러면 그때 제거되겠죠.
제일 처음 코드에서 addSubview: 한 다음에 [imageView2 release]; 해주세요.
그리고, 제일 처음부분에서 dealloc 호출 직접하는건 절대로 하지마세요.
Kenny님의 댓글
에고.. 그러고보니, 이글 1년전꺼네요.. ㅡ,.ㅡ;;;
JParker님의 댓글
좋은 정보 감사드립니다.