Od czasu aktualizacji do najnowszej wersji Xcode 3.2.1 i Snow Leopard otrzymuję ostrzeżenie
„format nie jest literałem ciągu i brak argumentów formatu”
z następującego kodu:
NSError *error = nil;
if (![self.managedObjectContext save:&error])
{
NSLog([NSString stringWithFormat:@"%@ %@, %@",
errorMsgFormat,
error,
[error userInfo]]);
}
Jeśli errorMsgFormat
jest NSString
z specyfikatorami formatu (np. "print me like this: %@"
:), Co jest nie tak z powyższym NSLog
wywołaniem? Jaki jest zalecany sposób naprawienia tego problemu, aby ostrzeżenie nie było generowane?
objective-c
warnings
string-formatting
nslog
Alexi Groove
źródło
źródło
NSLog()
może przyjąć jeden argument, gdy łańcuch formatu nie zawiera specyfikatorów formatu.Xcode narzeka, ponieważ jest to problem z bezpieczeństwem.
Oto kod podobny do twojego:
Ta ostatnia instrukcja NSLog będzie wykonywała odpowiednik tego:
To spowoduje, że NSLog będzie szukał jeszcze jednego argumentu typu string, ale takiego nie ma. Ze względu na sposób działania języka C, pobierze on ze stosu jakiś losowy wskaźnik śmieci i spróbuje traktować go jak NSString. Najprawdopodobniej spowoduje to zawieszenie programu. Teraz twoje łańcuchy prawdopodobnie nie zawierają% @, ale któregoś dnia mogą. Zawsze należy używać łańcucha formatu z danymi, które jawnie kontrolujesz, jako pierwszego argumentu funkcji pobierających ciągi formatujące (printf, scanf, NSLog, - [NSString stringWithFormat:], ...).
Jak podkreśla Otto, prawdopodobnie powinieneś zrobić coś takiego:
źródło
Ostateczna odpowiedź: jak powiedział Jon Hess, jest to kwestia bezpieczeństwa, ponieważ przekazujesz ciąg WHATEVER do funkcji oczekującej ciągu formatu. Oznacza to, że oceni wszystkie specyfikatory formatu W RAMACH dowolnego ciągu. Jeśli ich nie ma, super, ale jeśli są, mogą się zdarzyć złe rzeczy.
Zatem właściwą rzeczą do zrobienia jest na przykład bezpośrednie UŻYCIE łańcucha formatującego
W ten sposób, nawet jeśli w myNSString istnieją specyfikatory formatu, nie są one oceniane przez NSLog.
źródło
Nie polecam szczególnie tego używania, ponieważ ostrzeżenie JEST prawdziwym ostrzeżeniem .. w dynamicznym używaniu języka możliwe jest wykonanie pewnych czynności na łańcuchu (np. Wstawienie nowych informacji lub nawet zawieszenie programu) .. Jednak jest to możliwe wymusić tłumienie, jeśli WIESZ, że tak powinno być i naprawdę nie chcesz być o tym ostrzeżony.
#pragma GCC diagnostic ignored "-Wformat-security"
Powiedziałby GCC, aby tymczasowo zignorował ostrzeżenie o kompilacji. Ponownie, to niczego nie rozwiązuje, ale mogą wystąpić chwile, kiedy nie możesz znaleźć dobrego sposobu na faktyczne naprawienie problemu.
EDYCJA: Od czasu clang pragma uległa zmianie. Zobacz: https://stackoverflow.com/a/17322337/3937
źródło
Najszybszym sposobem rozwiązania tego problemu byłoby dodanie
@"%@",
jako pierwszego argumentu doNSLog
wywołania, tj.Chociaż prawdopodobnie powinieneś rozważyć odpowiedź Sixteen Otto.
źródło
Właśnie przekazałem zero, aby zanegować ostrzeżenia, może to zadziała dla ciebie?
NSLog (myString, nil);
źródło
myString
, pierwszy będzie w porządku, ale drugi usunie śmieci ze stosu. Lista podmiany w nigdy nieNSLog()
jest zakończona, @Sold. Istnieją dwie możliwości ustalenia, jak długa jest lista argumentów: wartość wartownicza lub co jest używane w i rodzina - kolejny argument, który umożliwia obliczenie liczby (np. Przez zliczenie specyfikatorów formatu).nil
printf()
Jeśli chcesz raz na zawsze pozbyć się ostrzeżenia „format nie jest literałem łańcuchowym i brakiem argumentów formatu”, możesz wyłączyć ustawienie ostrzeżenia GCC „Typecheck wywołuje printf / scanf” (GCC_WARN_TYPECHECK_CALLS_TO_PRINTF = NO) w ustawieniach kompilacji celu.
źródło
NSLog () oczekuje ciągu formatu, a przekazywany jest tylko ciąg. Nie musisz używać stringWithFormat :, możesz po prostu:
NSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])
A to sprawi, że ostrzeżenie zniknie.
źródło
FWIW, dotyczy to również programistów iPhone'a. Koduję względem zestawu SDK 3.1.3 i otrzymałem ten sam błąd z tym samym problemem (zagnieżdżenie stringWithFormat wewnątrz NSLog ()). Sixten i Jon szukają pieniędzy.
źródło
Po prostu poinformowanie kogokolwiek o użyciu
appendFormat
on NSMutableString może również spowodować wyświetlenie tego ostrzeżenia, jeśli próbujesz przekazać sformatowany ciąg w następujący sposób:Aby uniknąć tego ostrzeżenia, zamień powyższe na to:
Bardziej zwięzłe i bezpieczniejsze. Cieszyć się!
źródło
źródło
stringWithFormat
jest tu zbędne, kiedy możesz to zrobićNSLog(@"%@ %@, %@", errorMsgFormat, error, [error userInfo])