최신 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)을 비활성화 할 수 있습니다.