[objective-c] 경고 : “문자열 리터럴이 아니고 형식 인수가없는 형식”

최신 Xcode 3.2.1 및 Snow Leopard로 업그레이드 한 후 경고를 받았습니다.

“문자열 리터럴이 아니고 형식 인수가없는 형식”

다음 코드에서 :

NSError *error = nil;

if (![self.managedObjectContext save:&error]) 
{
    NSLog([NSString stringWithFormat:@"%@ %@, %@", 
       errorMsgFormat, 
       error, 
       [error userInfo]]);      

}

경우 errorMsgFormat입니다 NSString형식 지정자와 (예 : "print me like this: %@"), 위의 문제 무엇을 NSLog호출? 경고가 생성되지 않도록 수정하는 권장 방법은 무엇입니까?



답변

대괄호를 올바르게 중첩하고 있습니까? 나는 NSLog()당신이 그것을 전달하고있는 하나의 논쟁만을 취하는 것을 좋아하지 않는다고 생각 합니다. 또한 이미 서식을 지정합니다. 왜 이렇게하지 않습니까?

NSLog(@"%@ %@, %@", 
   errorMsgFormat, 
   error, 
   [error userInfo]);              

또는 errorMsgFormat하나의 자리 표시자가있는 형식 문자열 이라고 말 했으므로 이렇게 하시겠습니까?

NSLog(@"%@, %@", [NSString stringWithFormat:errorMsgFormat, error], 
   [error userInfo]);              


답변

이것이 보안 문제이기 때문에 Xcode가 불평하고 있습니다.

다음은 귀하와 유사한 코드입니다.

NSString *nameFormat = @"%@ %@";
NSString *firstName = @"Jon";
NSString *lastName = @"Hess %@";
NSString *name = [NSString stringWithFormat:nameFormat, firstName, lastName];
NSLog(name);

마지막 NSLog 문은 다음과 같은 것을 실행합니다.

NSLog(@"Jon Hess %@");

그러면 NSLog가 하나 이상의 문자열 인수를 찾게 될 것이지만 하나는 없습니다. C 언어가 작동하는 방식 때문에 스택에서 임의의 가비지 포인터를 선택하여 NSString처럼 처리하려고합니다. 이로 인해 프로그램이 충돌 할 가능성이 높습니다. 이제 문자열에 % @가 없을 수도 있지만 언젠가는 그럴 수도 있습니다. 항상 형식 문자열 (printf, scanf, NSLog,-[NSString stringWithFormat :], …)을 사용하는 함수에 대한 첫 번째 인수로 명시 적으로 제어하는 ​​데이터가있는 형식 문자열을 사용해야합니다.

Otto가 지적했듯이 다음과 같은 작업을 수행해야합니다.

NSLog(errorMsgFormat, error, [error userInfo]);


답변

최종 답변 : Jon Hess가 말했듯이 형식 문자열이 필요한 함수에 WHATEVER 문자열을 전달하기 때문에 보안 문제입니다. 즉, 어떤 문자열에서든 모든 형식 지정자를 평가합니다. 굉장하지만 만약 있다면 나쁜 일이 일어날 수 있습니다.

올바른 방법은 형식 문자열을 직접 사용하는 것입니다.

NSLog(@"%@", myNSString);

이렇게하면 myNSString에 형식 지정자가 있어도 NSLog에 의해 평가되지 않습니다.


답변

나는 이것을 사용하는 것을 특히 추천하지 않는다. 왜냐하면 경고는 진짜 경고이기 때문이다. 언어를 동적으로 사용하면 런타임에서 문자열에 작업을 수행 할 수있다. 이렇게해야한다는 것을 알고 있고 경고를 받고 싶지 않다면 강제로 억압합니다.

#pragma GCC diagnostic ignored "-Wformat-security"

GCC에게 컴파일 경고를 일시적으로 무시하라고 지시합니다. 다시 말하지만 문제를 실제로 해결하는 좋은 방법을 찾을 수없는 경우도 있습니다.

편집 : clang에서 pragma가 변경되었습니다. 참조 : https://stackoverflow.com/a/17322337/3937


답변

이를 수정하는 가장 빠른 방법 @"%@",NSLog호출에 첫 번째 인수로 추가하는 것입니다 .

NSLog(@"%@", [NSString stringWithFormat: ....]);

그러나 아마도 Sixteen Otto의 대답을 고려해야합니다.


답변

경고를 무효화하기 위해 방금 전무를 전달했습니다. 아마도 그게 당신에게 도움이 될까요?

NSLog (myString, nil);


답변

“문자열 리터럴이 아니고 형식 인수가없는 형식”경고를 한 번에 없애려면 대상의 빌드 설정에서 GCC 경고 설정 “printf / scanf에 대한 Typecheck 호출”(GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO)을 비활성화 할 수 있습니다.