Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected - retain

I'm verifying my app and I got a lot of this kind of warnings:
Object with a +0 retain count returned to caller where a +1 (owning) retain count is expected
This is an example of one of those methods that generate the warning (the warning is on the return line)
+ (vehicleInfo*) newWithNode: (CXMLNode*) node
{
if(node == nil) { return nil; }
return (vehicleInfo*)[[[vehicleInfo alloc] initWithNode: node] autorelease];
}
Is it something I should worry about?
How can I fix it?
Thanks in advance,
Samuel

You're getting the warning because you're violating the contract that you become an owner of objects created with a method named with new. Any code calling +newWithNode expects to be an owner of the return value and should later call -release to release it.
See the Objective-C Memory Management Policy for more details.

Following you link, the guide says:
Use autorelease to Send a Deferred release
You use autorelease when you need to send a deferred release message—typically when returning an object from a method. For example, you could implement the fullName method like this:
- (NSString *)fullName {
NSString *string = [[[NSString alloc] initWithFormat:#"%# %#",
self.firstName, self.lastName] autorelease];
return string;
}
You own the string returned by alloc. To abide by the memory management rules, you must relinquish ownership of the string before you lose the reference to it. If you use release, however, the string will be deallocated before it is returned (and the method would return an invalid object). Using autorelease, you signify that you want to relinquish ownership, but you allow the caller of the method to use the returned string before it is deallocated.
So, despite the warning, it seems I'm doing the right stuff, don't I?

Related

KVO notification with Core Data in Swift

When I generate an NSManagedObject subclass with swift, the property types are all #NSManaged, meaning I can't observe them. This is a problem when using bindings in a Cocoa application because updating the property frequently requires other properties to be 'updated'.
For example, if I add this method to my NSManagedObject subclass:
dynamic var ratePerPoint: Double {
guard pointsPerMonth > 0 else { return 0 }
return monthlyRate / Double(pointsPerMonth)
}
Then it's important that whenever I update the pointsPerMonth variable, which is part of the core data object, that I send a didChangeValueForKey("ratePerPoint") message.
If I don't, then the UI bindings don't update properly.
If ratePerPoint is a calculated property you have to implement keyPathsForValuesAffectingRatePerPoint in your NSManagedObject subclass.
+ (NSSet *)keyPathsForValuesAffectingRatePerPoint {
return [NSSet setWithObjects:#"monthlyRate", #"pointsPerMonth", nil];
}
Documentation: Registering Dependent Keys

ConcurrentModificationException with WeakHashMap

I have the code below but I'm getting ConcurrentModificationException, how should I avoid this issue? (I have to use WeakHashMap for some reason)
WeakHashMap<String, Object> data = new WeakHashMap<String, Object>();
// some initialization code for data
for (String key : data.keySet()) {
if (data.get(key) != null && data.get(key).equals(value)) {
//do something to modify the key
}
}
The Javadoc for WeakHashMap class explains why this would happen:
Map invariants do not hold for this class. Because the garbage
collector may discard keys at any time, a WeakHashMap may behave as
though an unknown thread is silently removing entries
Furthermore, the iterator generated under the hood by the enhanced for-loop you're using is of fail-fast type as per quoted explanation in that javadoc.
The iterators returned by the iterator method of the collections
returned by all of this class's "collection view methods" are
fail-fast: if the map is structurally modified at any time after the
iterator is created, in any way except through the iterator's own
remove method, the iterator will throw a
ConcurrentModificationException. Thus, in the face of concurrent
modification, the iterator fails quickly and cleanly, rather than
risking arbitrary, non-deterministic behavior at an undetermined time
in the future.
Therefore your loop can throw this exception for these reasons:
Garbage collector has removed an object in the keyset.
Something outside the code added an object to that map.
A modification occurred inside the loop.
As your intent appears to be processing the objects that are not GC'd yet, I would suggest using an iterator as follows:
Iterator<String> it = data.keySet().iterator();
int count = 0;
int maxTries = 3;
while(true) {
try {
while (it.hasNext()) {
String str = it.next();
// do something
}
break;
} catch (ConcurrentModificationException e) {
it = data.keySet().iterator(); // get a new iterator
if (++count == maxTries) throw e;
}
}
You can clone the key set first, but note that you hold the strong reference after that:
Set<KeyType> keys;
while(true) {
try {
keys = new HashSet<>(weakHashMap.keySet());
break;
} catch (ConcurrentModificationException ignore) {
}
}
for (KeyType key : keys) {
// ...
}
WeakHashMap's entries are automatically removed when no ordinary use of the key is realized anymore, this may happens in a different thread. While cloning the keySet() into a different Set a concurrent Thread may remove entries meanwhile, in this case a ConcurrentModificationException will 100% be thrown! You must synchronize the cloning.
Example:
Collections.synchronizedMap(data);
Please understand that
Collections.synchronizedSet(data.keySet());
Can not be used because data.keySet() rely on data's instance who is not synchronized here! More detail: synchronize(keySet) prevents the execution of methods on the keySet but keySet's remove-method is never called but WeakHashMap's remove-method is called so you have to synchronize over WeakHashMap!
Probably because your // do something in the iteration is actually modifying the underlying collection.
From ConcurrentModificationException:
For example, if a thread modifies a collection directly while it is iterating over the collection with a fail-fast iterator, the iterator will throw this exception.
And from (Weak)HashMap's keySet():
Returns a Set view of the keys contained in this map. The set is backed by the map, so changes to the map are reflected in the set, and vice-versa. If the map is modified while an iteration over the set is in progress (except through the iterator's own remove operation), the results of the iteration are undefined.

Proper Object Disposal In C++/CLI

Consider the following class:
public ref class Workspace
{
protected:
Form^ WorkspaceUI;
SplitContainer^ WorkspaceSplitter;
AvalonEditTextEditor^ TextEditor;
ScriptOffsetViewer^ OffsetViewer;
SimpleTextViewer^ PreprocessedTextViewer;
ListView^ MessageList;
ListView^ FindList;
ListView^ BookmarkList;
ListView^ VariableIndexList;
TextBox^ VariableIndexEditBox;
Label^ SpoilerText;
ToolStrip^ WorkspaceMainToolBar;
ToolStripButton^ ToolBarNewScript;
ToolStripButton^ ToolBarOpenScript;
ToolStripButton^ ToolBarPreviousScript;
ToolStripButton^ ToolBarNextScript;
ToolStripSplitButton^ ToolBarSaveScript;
ToolStripDropDown^ ToolBarSaveScriptDropDown;
ToolStripButton^ ToolBarSaveScriptNoCompile;
ToolStripButton^ ToolBarSaveScriptAndPlugin;
ToolStripButton^ ToolBarRecompileScripts;
ToolStripButton^ ToolBarCompileDependencies;
ToolStripButton^ ToolBarDeleteScript;
ToolStripButton^ ToolBarNavigationBack;
ToolStripButton^ ToolBarNavigationForward;
ToolStripButton^ ToolBarSaveAll;
ToolStripButton^ ToolBarOptions;
ArbitraryCustomClass^ CustomClassInstance;
public:
Workspace()
{
WorkspaceUI = gcnew Form();
WorkspaceSplitter = gcnew SplitContainer();
// ...
Form->Controls->Add(WorkspaceSplitter);
// ...
WorkspaceUI->Show();
}
~Workspace
{
// dispose stuff here
}
};
What would be the most efficient and elegant way to dispose an instance of the above class so that all of its memory is reclaimed by the GC during its next collection? Do I need to call delete explicitly on each member and/or reset them to nullptr?
NB. You may not need to do anything. Memory for objects is reclaimed by the GC when references no longer exist that point to it.
You only need to explicitly reclaim when an object implements IDisposable. In C++/CLI this maps to destructors.
So if none of the objects you're allocating need to be disposed, you can ignore the rest of this answer. But supposing they do...
Remove the ^ from each field and they will be reclaimed automatically.
It would also mean that they would be default-constructed automatically when the Workspace is constructed, which may save you a lot of gcnew stuff in your hand-written constructor.
That is, if you say:
Form WorkspaceUI;
Then you don't need to say:
WorkspaceUI = gcnew Form();
The compiler has already generated that for you - imagine it being inserted at the start of your constructor.
Nor do you need to dispose/delete anything.
Finally, you need to use . instead of -> to access members of the objects that you declare in this way:
Form.Controls->Add(WorkspaceSplitter);
Update:
In C++/CLI, handles to ref classes are declared with ^, and this is analogous to the way pointers to native classes are declared with *.
Also correspondingly, there needs to be a way to get a handle to an object. To get a pointer to a native object, we prefix with &. To get a handle to a ref object, we prefix with %. For example:
ref class Fred { };
// function that accepts a handle
void ping(Fred ^h) { }
// Elsewhere... declare object of type Fred
Fred f;
// Get handle to pass to function
ping(%f);
If repeatedly creating and deleting objects of your class leads to out-of-memory there are two possibilities:
You are inadvertently holding references to it (or something it allocates). See my answer to this question: Memory Leaks in C# WPF (it doesn't have anything specific to do with C# or WPF really, it's just a matter of using the debugger interactively)
You need to call Dispose on one or more of the objects you allocate inside your class.
If it's the latter, in C++/CLI there is built-in support for calling Dispose automatically - C++/CLI treats a disposable object as if it was a C++ ref class with a destructor.
So if you delete a handle, you're calling Dispose on the object it points to.
Or if (as I suggest above) you simply have member objects, you don't even need to explicitly delete. When the outer containing class is destructed (i.e. something calls its Dispose method), it will automatically call Dispose on any member objects that require it.

Problem with UICustomSwitch,

I am using UICsutomSwitch for my application. When I try to create it, I am getting an exception like,
Terminating app due to uncaught exception 'NSRangeException', reason: '* -[NSArray objectAtIndex:]: index 2 beyond bounds for empty array'
My code is as follows,
UICustomSwitch.h
#import <Foundation/Foundation.h>
#interface UICustomSwitch : UISwitch
{
}
-(void)setLeftLabelText:(NSString *)labelText;
-(void)setRightLabelText:(NSString *)labelText;
#end
UICustomSwich.m
#import "UICustomSwitch.h"
#implementation UICustomSwitch
-(UIView *)slider
{
return [[self subviews ] lastObject];
}
-(UIView *)textHolder
{
return [[[self slider] subviews]objectAtIndex:2];
}
-(UILabel *)leftLabel
{
return [[[self textHolder] subviews]objectAtIndex:0];
}
-(UILabel *)rightLabel
{
return [[[self textHolder] subviews]objectAtIndex:1];
}
-(void)setLeftLabelText:(NSString *)labelText;
{
[[self leftLabel] setText:labelText];
}
-(void)setRightLabelText:(NSString *)labelText
{
[[self rightLabel]setText:labelText];
}
#end
View Controller:
UICustomSwitch* switchView=[[[UICustomSwitch alloc]initWithFrame:CGRectMake(200,5,90,30)]autorelease];
[switchView setLeftLabelText:#"F"];
[switchView setRightLabelText:#"M"];
[switchView addTarget:self action:#selector(genderAction:) forControlEvents:UIControlEventValueChanged];
[elementView addSubview:switchView];
I am getting exception at " return [[[self slider] subviews]objectAtIndex:2];" call. I don't know what is the wrong, Can you guys please suggest me on this.
Thanks in advance,
Sekhar.
I ran across this issue and found the answer here:Custom UISwitch Text
Basically in iOS 4, there were UILabel's in the UISwitch's subviews that represented the "On/Off" labels. In iOS 5, there are no UILabels in the subviews array (hence the array error you're getting). The above link offers an external class you can download and customize. In my opinion, it seems like Apple is discouraging customization of UISwitch. The functionality you're after could be accomplished another way (segmented control, simulated checkbox, etc).
Also, in the given link above, the author proposes that the issue might be with not including armv6. I tried this and it does not fix the problem.
The exception indicates you are attempting to access an element of the array that is out of bounds (in a place that is larger than the actual size of the array).
You can use breakpoints and/or NSLog() calls carefully placed in your code to determine if this array ever is not-empty, and if that is so, you can continue to use these calls to find out just where the array becomes empty.
Clearly if the array is empty then the switch is setup differently than you expect it to be.

DynamicMethod code unverifiable in .Net 4.0 (found ref 'this' pointer... expected ref '<>f__AnonymousType1`)

Was using this solution to convert anonymous types to dictionaries using reflection.emit. Was working fine until I changed to .Net 4.0 from 3.5.
Now, I'm getting the "System.Security.VerificationException: Operation could destabilize the runtime." error.
Converted the anonymously loaded dynamic method to one hosted in a dynamic assembly, saved it, then ran peverify.exe on it to find out what was wrong.
Got: [IL]: Error: [DynamicAssemblyExample.dll : MyDynamicType::MyMethod][offs
et 0x0000000D][found ref ('this' ptr) 'MyDynamicType'][expected ref '<>f__AnonymousType1`3[System.String,System.Int32,System.Byte]'] Unexpected type on the stac
k.
[IL]: Error: [DynamicAssemblyExample.dll : MyDynamicType::MyMethod][offs
et 0x0000000D] Method is not visible.
2 Error(s) Verifying DynamicAssemblyExample.dll
The code:
foreach (PropertyInfo property in itemType.GetProperties(attributes).Where(info => info.CanRead))
{
// load Dictionary (prepare for call later)
methIL.Emit(OpCodes.Ldloc_0);
// load key, i.e. name of the property
methIL.Emit(OpCodes.Ldstr, property.Name);
// load value of property to stack
methIL.Emit(OpCodes.Ldarg_0);
methIL.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null);
// perform boxing if necessary
if (property.PropertyType.IsValueType)
{
methIL.Emit(OpCodes.Box, property.PropertyType);
}
// stack at this point
// 1. string or null (value)
// 2. string (key)
// 3. dictionary
// ready to call dict.Add(key, value)
methIL.EmitCall(OpCodes.Callvirt, addMethod, null);
}
Is there a way to derefence the pointer to the actual property? Or do I have to cast it somehow? Any pointers?
Regards!
Sorry guys, made a mistake, since the actual dynamic method creates a delegate type that acts on the instance of the anonymous (or non-anonymous) type, the Ldarg_0 code is looking for a something that is not there in this debug implementation.
So I, changed it to OpCodes.Ldnull.
var attributes = BindingFlags.Instance | BindingFlags.Public | BindingFlags.FlattenHierarchy;
foreach (PropertyInfo property in itemType.GetProperties(attributes).Where(info => info.CanRead))
{
// load Dictionary (prepare for call later)
methIL.Emit(OpCodes.Ldloc_0);
// load key, i.e. name of the property
methIL.Emit(OpCodes.Ldstr, property.Name);
// load value of property to stack
methIL.Emit(OpCodes.Ldnull);
//methIL.Emit(OpCodes.Castclass, itemType);
methIL.EmitCall(OpCodes.Callvirt, property.GetGetMethod(), null);
// perform boxing if necessary
if (property.PropertyType.IsValueType)
{
methIL.Emit(OpCodes.Box, property.PropertyType);
}
// stack at this point
// 1. string or null (value)
// 2. string (key)
// 3. dictionary
// ready to call dict.Add(key, value)
methIL.EmitCall(OpCodes.Callvirt, addMethod, null);
}
But I still get a method not visible error after peverifying it. Is it that get methods for properties of anonymous types are not visible via reflection?
Just a suggestion, have you tried to rewrite the code that emits IL to actually write to the dictionary - i.e. no Reflection.Emit ? My bet is that the generated IL is not proper in some way, not the code that accesses the anonymous type.

Resources