2014-02-03 14 views
1

나는 알고있는 몇 사람에게 물어 봤지만 너무 바빠서 조언을 구하지 못했습니다.관리되는 동적 저장소를 사용하는 간단한 프로그램에서 Segfaulting

나는 alloc/dealloc이 으로 처리되는 방식으로 벽을 계속 달리고 있습니다. 다음 중 하나가 내게 열매를 맺고 있습니다 ... 이것은 내 주간에 디버깅하려고 시도한 코드의 입니다. 여기

는 (분명히하지 않고) 내가 발생해야한다고 생각 무엇 :

  • 내가
  • 내가 그렇게 현재 풀에 그것을 넣어 객체와 오토 릴리즈를 만들고 풀을 할당 풀을 풀 때 dealloc이 실행됩니다.
  • 테스트 클래스에는 내부 용 NSString var 만 있습니다.
  • NSString은 해당 클래스의 dealloc 메소드에서 해제됩니다.
  • 나는 테스트 개체를 해제하려고 않습니다 수영장, 그것이 있는 NSString을 해제하려고으로 그것은 즉시 할당 해제의 방법에 세그먼테이션 폴트 (segfault)
  • 를 놓습니다.

과거에는 문제가 사라질 때까지 바이킹으로 구매했습니다. 그러나 지금은 스토리지 문제를 해결했음을 증명할 수 있어야하는 개발 단계에 도달했습니다.

지난 한 해 동안 ObjC 스토리지 관리에 대한 많은 문서를 읽었습니다. 불행히도 실제로이 모든 것이 실제로 에 어떻게 부합되는지에 대해서는 의견이 분분한 것 같습니다.이 혼란은 성장한대로 이 관리되는 스토리지 프로세스의 일부가 아니었던 사람들에게는 도움이되지 않습니다. (RTOS의 어셈블리 코드에서 DSA를 작성하는 데 어려움을 겪고있다) 어려움을 겪고 있다면 다른 사람들이 직면해야만하는 것을 상상할 수 있습니다.

정말 유용 할 한 가지는 오류를 제거하는 코드를 테스트하는 방법에 대한 설명서입니다. 나는 그런 정보가 존재한다고 확신하고, 여기 조금은 조금씩 뛰어 넘었지만, 조각들이 모두 깔끔하게 맞지는 않습니다. 나는 또한 enableDoubleReleaseCheck를 사용하고있다.

테스트 케이스를 단순하게 유지하기 위해 생략했습니다. 가장 환영과 많이 주시면 감사하겠습니다

@interface Command:NSObject {NSString *cmdline;} 
- (id) init; 
- (void) dealloc; 
@end 

@implementation Command 
- (id) init { 
    if (!(self = [super init])) {return nil;} 
    cmdline = [NSString stringWithCString: "This is a test"]; 
    return self; 
} 

- (void) dealloc { 
    printf ("Release cmdline\n"); 
    [cmdline release]; 
    printf ("Release cmdline done\n"); 
    [super dealloc]; 
} 
@end 

int main(int argc, char *argv[]) { 
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; 
    Command *cmd   = [[Command new] autorelease]; 

    @try {[pool release];} 
    @catch (NSException *e){ 
    printf ("Fatal [%s] %s\n", [[e name] cString], [[e reason] cString]);} 

    printf ("Done\n"); 
    exit (EXIT_SUCCESS); 
} 

조언

./CommandTest 
Release cmdline 
Segmentation fault (core dumped) 


/* Makefile strings: 
    OBJC = gcc -g -fobjc-exceptions -fconstant-string-class=NSConstantString -D_NATIVE_OBJC_EXCEPTIONS -I /usr/include/GNUstep 

    CommandTest: CommandTest.o $(OBJC) -g -o CommandTest CommandTest.o -lobjc -lgnustep-base */ 

#include <stdio.h> 

수입 :

여기 CommandTest.m, 결과 완전한 테스트 케이스입니다.

cmdline = [NSString stringWithCString: "This is a test"]; 

당신은 객체를 유지하지 않는, 그래서 효과적으로 카운트를 유지 0으로 돌아와 곧 오토 릴리즈 것 :

답변

1

문제는 여기에있다.

2

문자열이 두 번 릴리스됩니다. +[NSString stringWithCString:]은 자동 렌더링 된 객체를 만듭니다.자동으로 가장 가까운 autorelease pool에 저장됩니다.

풀을 풀면 문자열도 해당됩니다. 그런 다음 문자열 소유자가 release을 다시 보내면 예외가 발생합니다. (이 두 가지는 실제로 어느 순서로든 발생할 수 있지만 문제가되지는 않습니다.)

Command 개체는 NARC 규칙을 따르지 않았기 때문에 참조 문자열의 관점에서 실제로 문자열을 소유하지 않습니다 . 문자열에 new, alloc, retain 또는 copy을 사용하지 않았습니다. autorelease 풀은 유일한 소유자입니다. 따라서 Command이 나중에 release을 보내면 오류가 발생합니다. 수영장 모두 다음과 Command 소유권을 가질 것이며, 나중에 release를 전송해야 할 것입니다 - -하거나 같이 alloc를 사용하여 만들 당신이 그것을 만들 때

솔루션은 오토 릴리즈 문자열로 retain를 보내는 것입니다 [[NSString alloc] initWithCString:]. 그렇다면 Command은 단독 소유자가됩니다.

+0

그 무서운 부분은 ... 클래스에서 내부 사용을 위해 생성 된 객체가 이미 자동 릴리즈되거나 유지되는 시점과 그렇지 않은 시점을 어떻게 알 수 있습니까? 나는 당신이 그것을 할당하면, 그것을 풀어 놓는 것이 일반적인 규칙이라고 생각했다. –

+0

규칙에 따라. 'new' 또는'alloc'을 사용하여 생성하면 소유 된 참조입니다. 당신이하지 않는다면, 그것은 당신의 관심사는 아니지만 (실제로는 자동 풀 풀에 거의 확실합니다). 이 규칙은 당신이'alloc'_을 사용하여 그것을 할당하는 것이다. –

+0

GNUStep의 관련 문서 섹션은 다음과 같습니다. http://www.gnustep.org/resources/documentation/Developer/Base/ProgrammingManual/manual_3.html#SEC43 –