2014-07-23 4 views
0

내 코드에서 문제가 발생하는 메모리 누수가 있습니다. 이 라인에서 특히, 나는 EXC_BAD_ACCESS 받고 있어요 (코드 = 1) : 다음 코드에서CTLineRef에서 메모리 누수가 발생합니까?

CGFloat xStart = origin.x + CTLineGetOffsetForStringIndex(line, index, NULL); 

:

- (CGRect)firstRectForNSRange:(NSRange)range; 
{ 
    NSInteger index = range.location; 

    NSArray *lines = (__bridge NSArray *) CTFrameGetLines(self.textFrame); 
    NSInteger linesCount = [lines count]; 
    CFIndex paragraphSpacingOffset = (self.paragraphSpacing > 0) ? 1 : 0; 

    for (NSInteger i = 0 + paragraphSpacingOffset; i < (linesCount - paragraphSpacingOffset); i++) 
    { 
     CTLineRef line = (CTLineRef) CFBridgingRetain([lines objectAtIndex:i]); 
     CFRange lineRange = CTLineGetStringRange(line); 
     NSInteger localIndex = index - lineRange.location; 

     if (localIndex >= 0 && localIndex < lineRange.length) 
     { 
      NSInteger finalIndex = MIN(lineRange.location + lineRange.length, range.location + range.length); 

      CGPoint origin; 
      CTFrameGetLineOrigins(self.textFrame, CFRangeMake(i, 0), &origin); 
      CGFloat xStart = origin.x + CTLineGetOffsetForStringIndex(line, index, NULL); 
      CGFloat xEnd = origin.x + CTLineGetOffsetForStringIndex(line, finalIndex, NULL); 
      CGFloat ascent, descent; 
      CTLineGetTypographicBounds(line, &ascent, &descent, NULL); 
      CFRelease(line); 
      return CGRectMake(xStart, origin.y - descent, xEnd - xStart, ascent + descent); 
     } 
     else 
     { 
      CFRelease(line); 
     } 
    } 

    return CGRectNull; 
} 

내가 확인 한대로 메모리 누수의 거의 확실 해요 코드를 철저히. 코어 Foundation 객체 line을 위의 방법으로 잘못 관리하는 방법을 알 수 있습니까? line이 (가) CTLineGetOffsetForStringIndex (으)로 다시 전송 될 때 문제가 발생합니까?

답변

1

귀하의 문제는 거의 확실하게 여기에 있습니다 :

CTFrameGetLineOrigins(self.textFrame, CFRangeMake(i, 0), &origin); 

이 말한다 "origin하여 메모리에 프레임의 끝의 끝을 통해 인덱스 i에서 라인 기원을 지적하기 위해 써주세요." 불행히도 origin은 단 하나의 요소를 가리키고 있으므로 나머지 스택 전체를 걸을 것입니다. 나는 당신이 CFRangeMake(i, 1)을 의미한다고 생각합니다.

기타 참고 사항 :

당신은 CFArray하고있는 NSArray 사이를 이동 여기에 많은 복잡성을 만들. 그냥 CFArray를 사용하는 경우 코드가 훨씬 더 간단 할 것이다 :

CFArrayRef lines = CTFrameGetLines(self.textFrame); 
CFIndex linesCount = CFArrayGetCount(lines); 
... 

    CTLineRef line = (CTLineRef)CFArrayGetValueAtIndex(lines, i); 

이런 식으로 이렇게, 당신은 CFRelease()에 대한 호출이 필요하지 않습니다. 현재 CFRelease으로 전화하는 유일한 이유는 CFBridgingRetain()으로 전화하기 때문입니다. 모든 것이 복잡해지기 때문입니다. 가끔 NSArray로 넘어가는 것은 정말 좋은 일이지만,이 경우에는 그렇지 않습니다.

+0

감사합니다. 롭, 평생만큼 생명의 은인입니다. –

관련 문제