4 ms·
Always use a string literal as the first argument to NSLog or other printf type functions, but I don’t think the author correctly identified the cause of the cr
by david2ndaccount 5y ago
Always use a string literal as the first argument to NSLog or other printf type functions, but I don’t think the author correctly identified the cause of the crash. I believe floating point arguments are passed in registers, so you’ll just get whatever happens to be there. Besides, just reading value arguments like that should read junk from your stack, not a seg fault. Maybe he redacted the actual argument? An accidental %s or %n could lead to this behavior as it interprets junk as a pointer that is then accessed.
- saagarjha 5y agoApple's va_args ABI passes arguments on the stack. The actual argument works, but in the actual crashing case the URL was actually printed twice (the crasher was something like NSLog("\(url) \(error)"), the latter of which contained the error string again.)
- smallduck 5y agoIndeed the intent, though not expressed in the Objective-C declaration through the type system, is that the format string is a string literal. However the intent of the Swift call described in the article is indeed that of a string literal with 2 data "parameters". So is the correct use of NSLog in this case is this: NSLog("%@", "Failed to get modification date at URL: \(url) - \(error)") This should really be the behavior of NSLog in Swift, that it expands not to the variadic NSLog(format-string-parameter, objc-object-parameters..) but to NSLog(@"%@", string-parameter)
- azinman2 5y agoCorrect would be NSLog(“Failed to get modification date at URL: %@ - %@“, url.absoluteString, error.localizedDescription)
- tialaramex 5y agoSwift explicitly knows the difference between this construction and an actual string literal. Its type system considers "Foo" to be a StaticString, while "Foo \(something)" is merely a String, because it will need runtime allocation to calculate the actual value. A StaticString is actually a cheaper representation as well as needing to be distinguished for this reason. So a native Swift API would be able to distinguish and refuse to let you provide this String where a StaticString is the appropriate thing, I am not an Apple expert to say whether this would be possible / easy for the NSLog binding, if it was possible to do this it should have been done.
- saagarjha 5y agoNSLog takes dynamic strings just fine. Arbitrarily constraining it to only accept StaticStrings would break valid Swift programs. I wouldn't necessarily be opposed to it, but it's certainly not something that can be done without thoughtful consideration of the side effects.
- dwaite 5y agoIn general, it is valid to resolve localized strings for use as format strings, which means that it is valid to have dynamic format strings at runtime. NSLog might be considered an exception vs other Objective-C usage of format strings - but it might also not be worth having a singular special case.