Is this NSString a memory leak? - ios

NSString *pDescText = #"blablabla";
pDescText = [NSString stringWithFormat:#"%# %#",skProduct.localizedDescription,formattedPrice];
Does this produce a memory leak when I reassign pDescText in line 2?

If you are using ARC, you don't need to worry about these kinds of leaks.
If you are using MRC, you don't have a leak because:
You only need to release objects that you have a received a reference to by sending messages which contain new alloc retain or copy. In neither of these lines have you done this so you don't have an owned reference to pDescText. Furthermore, in the first line you are using a string literal, which is something that yo don't have to worry about memory management for.
And I have to say this pDescText is not a good name to use for a variable in Cocoa. We don't use hungarian notation (so the p to indicate a pointer isn't needed) and full, descriptive variable names are the norm. So instead of pDescText a more experienced Cocoa developer would use descriptiveText or even productDescription or description if that is enough for the context.

No, NSString convenience constructors return an autoreleased object.

Related

#synchronized parameter with same value but different reference?

I have a question about the parameter that #synchronized take, I have read the Apple document about synchronisation but still I don't have a clear idea.
I have a case that #synchronized will take a string property inside some object like this :
#synchronized(someObject.A)
since A is a NSString object and in some cases will carry the same value but from different someObject is this will guarantee the locking for all objects with same A values?
It's worth noting that NSString has some special cases that are handled magically.
NSString *s1 = #"Test string";
NSString *s2 = #"Test string";
Here, s1 and s2 are actually compiled to access the same memory address, even though they are different variables and could be instantiated in completely different places within the application.
However, if you are loading the data on-the-fly or using one of the construction methods for NSString instead of hard-coding it, strings that match character-for-character will not share the same memory.
You can consider this the difference between comparing with == and isEqualToString:. #synchronized only ever uses the == result.
So, to answer your question: maybe.
If you are using hard-coded values of the form #"some string" within your application, your #synchronized command will link to all objects that share the same textual value for A.
If you are creating NSString objects by any other means, your #synchronized command will only link to objects that point to the exact same NSString object.
The synchronization will be done on whatever object someObject.A is currently referencing. The important piece is the actual object you use #synchronized on.
If you assign the same string to two completely difference properties and you then use #synchronized on those two completely different properties, it will work since both point to the same string.
The following example may help:
// In one method
#synchronized(someObject.A) {
}
// In another method
NSString *foo = someObject.A;
#synchronized(foo) {
}
The above two blocks will be thread safe on the same string object.

NSString and NSMutableString memory considerations

I am trying to wrap my head around NSString and NSMutableString, and how they affect memory.
In my research, I've concluded that if I create an NSString object and give it a value, then change the value later, the original object is replaced by another with the new value.
My question is, in the case of changing the value of an NSString. When the value of the NSString is changed and the object pointed to is replaced by a new object, what happens to the original object? Is this a memory leak?
Thanks! V
NSStrings can contain string literals, which are compile time constants, and string objects, which instead are instantiated dynamically at runtime.
In case of string literals, there is no dynamic instantiation, so they won't affect memory at runtime. Assigning a literal value to a NSString variable
NSString *myString = #"string1";
then assigning another literal value
myString = #"string2";
doesn't make any change to the amount of available memory.
In case of string objects instead memory does change. If you have a variable of type NSString and assign it a dynamic string, such as
NSString *myString = [NSString stringWithFormat:#"String %d", 1];
a new NSString instance is allocated, initialized with the provided string, and assigned to the myString variable.
If later you assign a new dynamic value
myString = [NSString stringWithFormat:#"String %d", 2];
a new NSString instance is created, but it doesn't replace the old one. Both are instantiated and in memory.
When using ARC though the first NSString instance, if no longer referenced, will be released because not being used. This is handled automatically, so nothing must be done from code.
Maybe you're more interested in the fact that at some time the new and old instances use memory - but that's temporary until the unused instance is released.
To answer to your concern, no, there is no memory leak. String literals persist for the entire app lifetime, since they are constants. String objects are allocated and released (deallocated), and deallocation is automatically handled by ARC.
Of course this is a general concept that applies to any dynamically instantiated class, not just NSString - but doesn't apply to primitive data type (int, boolean, float, etc.), because variables of those types hold the actual value, not a pointer to the area in memory where the value is. In case you are wondering, primitive data types don't generate memory leaks.
The original NSString will be released by the system and so, won't cause any leak.

CFStringRef to NSString ARC leaking. Why?

I have been looking around for the correct way to go from CFStringRef to NSString in ARC to avoid memory leaks and some of the main voted answers suggest:
NSString * string = (__bridge NSString *)cfString;
I am using that approach here but when profiling the app I still get a memory leak in this small method [see attached image].
So, I am not sure how to fix this. Anybody has the solution to this problem?
Thank you
So, apparently adding the CFRelease(ext) before the return fixed the leak. Problem is I don't think I fully understand the reason. I thought that the line:
NSString * extension = (__bridge NSString*)ext
Would take ownership of the Core Foundation ext string and handle the release.
Can anybody explain what is going on here exactly?
As per the de-facto "standard" Cocoa naming convention, functions that contain Create or Copy in their name return an object with a reference count of 1. You have to transfer this reference count into ARC-land so that ARC can take care of it. You use the __bridge_transfer keyword for this purpose.
NSString *string = (__bridge_transfer NSString *)cfString;
Release the ext object or use __bridge_transfer.
Let me explain this a bit in the way I understand it:
__bridge – Normal casting. The retain count of casted object is partially managed by ARC and partially manually. You need to release the existing ownership on the CF side.
__bridge_transfer – “Converts CF object to NS object.” The retain count of casted object is fully managed by ARC. Existing ownership on the CF side is disposed for you.

In ios will NSString = NSString cause memory leaks?

I've seen some answers but those didn't expand enough and I think they were before ARC was introduced.
So if I have two NSSstring can I set
string1 =string2;
or
NSString * a1=#"String";
al=#"Lead";
without causing memory leaks or other problems?
Edit: What about view controller or delegate properties set to (copy, nonatomic)?
Edit2: It should be NSString *al=#"String". I hope this doesn't change the idea that it doesn't leak.
No, assigning and re-assigning string literals will not cause a memory leak. You only need to worry about memory leaks when not using ARC and assigning something that uses alloc, retain, copy, mutableCopy or a method prefixed with new.
NSString a1=[#"String" mutableCopy];
al=#"Lead";//This will cause a leak since you called copy above.
See the Advance Memory Management Rules for details.
neither would leak in ARC.
however, you might want to be aware that you are dealing with a reference in this case -- no implicit copy is performed (unless you use a copy or copy-qualified property).
Edit: What about view controller or delegate properties set to (copy, nonatomic)?
for NSStrings? yes, copy should be the default for NSStrings. nonatomic should be the default for everything. of course, there are exceptions to this -- when you might deviate from the defaults.
Your code is safe and will not leak. Cocoa and NSStrings are quite smart about how they deal with these issues.
You can end up with other interesting things happening because NSStrings are immutable, and you can get weirdness if you try to worry about the pointers themselves. But your examples don't suffer from these issues.

Why setting value with "self" cause memory leak?

I need to understand why in this code i get a memory leak if i assign value to ws_data variable using self.ws_data and not if i use only ws_data.
self.ws_data is a #property (copy)NSString *, released on dealloc.
dispatch_queue_t ws_queue = dispatch_queue_create("ws check win", NULL);
dispatch_async(ws_queue, ^{
self.ws_data = [[NSString alloc]initWithContentsOfURL:url];
});
dispatch_release(ws_queue);
Thank you!
self.variableName accesses the variable through its accessors. Because your ws_data NSString is set to copy in its property declaration, the string is retained when you set it through that declaration.
Not using self. references the ivar without going through those accessors. It also means the variable isn't copied, so it will vanish when references to it disappear (like at the end of your method).
Odds are you want the copy. You just need to release it when you're done, as you do in your dealloc.
Are you retaining it somewhere else, making this access a second retention?
If I understand things correctly (and I quite possibly don't as I've not be doing iOS development for very long at all) in this instance, as you're using the copy attribute on the property, what you're doing when you use self.ws_data is effectively calling the copy method on an already alloced NSString, which is creating a separate instance of the NSString with a retain count of one.
However, the original NSString (that's being alloced in your above sample) isn't being released at any point, hence the leak.
You could use...
self.ws_data = [[[NSString alloc]initWithContentsOfURL:url] autorelease];
...instead, I'd have thought.

Resources