2009-08-04 4 views
2

내가 최근 NSLog에서이 이상한 행동 (...) 추적 30 분을 낭비 :NSLog (...) 부적절한 형식 지정자가 다른 변수에 영향을 줍니까?

NSString *text = @"abc"; 
long long num = 123; 
NSLog(@"num=%lld, text=%@",num,text); //(A) 
NSLog(@"num=%d, text=%@",num,text); //(B) 

라인 (A)는 예상 "NUM = 123, 텍스트 = ABC"하지만 행을 인쇄를 (B)는 "num = 123, text = (null)"을 인쇄합니다.

분명히 long long%d으로 인쇄하는 것은 실수이지만, 누군가 text이 null로 인쇄되는 이유를 설명 할 수 있습니까?

+0

-Wall 옵션으로 컴파일하면 컴파일러에서 이와 같은 문제에 대해 경고합니다. 경고가 항상 빌드를 깨뜨릴 수 있도록 -Werror도 강력히 권장합니다. –

+1

@Adam Rosenfield, ala'-Wformat'와 같은 형식 검사를 지원하는 메모는 gcc/objc에서 항상 조금 헷갈 렸습니다. 이것은 컴파일러의 최신 버전에서 더 좋아지고있는 것처럼 보입니다. 그러나 Xcode 3.1에서 빠른 체크를했고 위의 오류를 포착하지 않았습니다. – johne

+0

-Wformat는 C 문자열 (printf와 같은)에서만 작동하고 NSString * 객체 상수 (NSLog가 사용하는)를 완전히 파싱 할 수 없으므로 오류를 포착하지 않습니다. –

답변

9

스택에서 메모리 정렬이 엉망입니다. 나는 당신이 x86 프로세서를 가진 최신 애플 제품을 사용한다고 가정한다. 두 경우 모두에서 스택처럼 보이는 계정에 이러한 가정을 촬영 :

 
    |  stack   | first | second | 
    +---------------------+-------+--------+ 
    |  123   |  | %d | 
    +---------------------+ %lld +--------+ 
    |   0   |  | %@ | 
    +---------------------+-------+--------+ 
    | pointer to text | %@ |ignored | 
    +---------------------+-------+--------+ 

먼저 상황에서 당신은 스택에 8 바이트 다음 4 바이트를 넣어. 그리고 NSLog는 스택 12 바이트 (%lld의 경우 8 바이트, %@의 경우 4 바이트)를 다시 가져 오라고 지시합니다.

두 번째 상황에서는 NSLog가 먼저 4 바이트 (%d)를 가져 오도록 지시합니다. 변수가 8 바이트 길이이고 실제로 작은 숫자를 보유하고 있기 때문에 상위 4 바이트는 0이됩니다. 그러면 NSLog가 텍스트 인쇄를 시도 할 때 스택에서 nil이 걸릴 것입니다.

Obj-C에서 nil으로 보내는 메시지가 유효하므로 NSLog는 을 nil으로 보내고 아무 것도 얻지 않고 인쇄합니다 (null).

Objective-C가 추가 된 C에 불과하기 때문에 호출자는이 모든 혼란을 해결합니다.

1

varargs의 구현 방법은 시스템에 따라 다릅니다. 그러나 인수가 다른 크기 일지라도 인수가 버퍼에 연속적으로 저장된다는 것은 일어날 가능성이 높습니다. 따라서 인수의 첫 번째 8 바이트 (long long int의 크기로 가정)는 long long int이고 다음 4 바이트 (시스템의 포인터 크기라고 가정)는 NSString 포인터입니다. 당신이이 int 다음 포인터를 기대하는 기능을 말할 때

는 다음에, 포인터 될 수있는 다음 4 바이트 (즉,이 int의 크기의 가정) 처음 4 바이트가 int이 될 것으로 기대합니다. 특정 엔디안 및 시스템의 인수 배열 때문에 long long int의 처음 4 바이트는 숫자의 최하위 바이트가되므로 123을 인쇄합니다. 그런 다음 객체 포인터의 경우 다음 4 바이트를 읽습니다. 이 경우 숫자의 최상위 바이트이며 모두 0이므로이 포인터는 nil 포인터로 해석됩니다. 실제 포인터는 결코 읽히지 않습니다.

관련 문제