Re: string pointer
Quincey Morris
On Mar 1, 2018, at 04:13 , Gerriet M. Denkmann <g@...> wrote:
So, here’s what’s going on. It’s a bit messy. — A pointer has an ownership attribute, which is __strong by default, but can be explicitly specified as __weak or __autoreleasing. In your code, variable “s” is __strong by default. — A pointer to a pointer needs to know the ownership of the pointee, and there is no default (in most cases), so you get the error "Pointer to non-const type 'NSString *' with no explicit ownership” for your declaration of “stringPointer”. — If you specify the actual ownership explicitly: NSString *__strong*stringPointer = needReason ? &s : NULL; that error goes away, but there is still an error on the call: “Passing address of non-local object to __autoreleasing parameter for write-back”. That’s because a pointer to a pointer that’s a method parameter *does* have a default pointee ownership, “__autoreleasing”. (When you added the explicit “__autoreleasing”, you didn’t change anything that wasn’t already assumed.) — So, you can declare your “computeFor:” method like this: - (NSUInteger)computeFor: (NSUInteger)arg reason: (NSString *__strong*)reason and everything would be just great, and this is the safest route. The only irritation is that every "NSString**” you pass into “computeFor:reason:” is going to need to be explicitly annotated, including those that pass through other methods, so the need to annotate is going to ripple outwards across your code. — This solution: NSUInteger c = [self computeFor:42 reason:needReason ? &s : nil]; is AFAIK a bit dangerous. The “computeFor:reason:” method stores an *autoreleased* string pointer into its output parameter, so “s” will end up containing this autoreleased pointer when “needReason” is true. That autoreleased pointer is a ticking time bomb that will explode if it’s still being used somewhere when its autorelease pool is drained (which could be a *lot* later, leading to hard-to-find bug) without being owned somewhere else. Whether this is a problem depends on what you do with “s” next. FWIW, all APIs that have a "NSError**outError” parameter have this same danger. (Charles Srstka pointed this out a few months ago.) Our apps work because the unowned pointer usually gets thrown away fast, or gets stored somewhere that gives it an extra retain. |
|