Bug 16208 - NSDictionary this[string] returns disposed NSString when key equals to value
Summary: NSDictionary this[string] returns disposed NSString when key equals to value
Status: RESOLVED DUPLICATE of bug 7723
Alias: None
Product: iOS
Classification: Xamarin
Component: XI runtime ()
Version: 7.0.3.x
Hardware: Macintosh Mac OS
: --- normal
Target Milestone: Untriaged
Assignee: Rolf Bjarne Kvinge [MSFT]
Depends on:
Reported: 2013-11-13 18:48 UTC by Yuri Tikhomirov
Modified: 2013-11-14 09:43 UTC (History)
2 users (show)

Is this bug a regression?: ---
Last known good build:

An example project reproducing the problem. (7.67 KB, application/zip)
2013-11-14 07:19 UTC, Yuri Tikhomirov
Watch results in my project (70 bytes, text/plain)
2013-11-14 07:53 UTC, Yuri Tikhomirov
Watch results in my project (61.52 KB, image/png)
2013-11-14 07:55 UTC, Yuri Tikhomirov
A project that uses Resources class with static instance (8.02 KB, application/zip)
2013-11-14 08:25 UTC, Yuri Tikhomirov

Notice (2018-05-24): bugzilla.xamarin.com is now in read-only mode.

Please join us on Visual Studio Developer Community and in the Xamarin and Mono organizations on GitHub to continue tracking issues. Bugzilla will remain available for reference in read-only mode. We will continue to work on open Bugzilla bugs, copy them to the new locations as needed for follow-up, and add the new items under Related Links.

Our sincere thanks to everyone who has contributed on this bug tracker over the years. Thanks also for your understanding as we make these adjustments and improvements for the future.

Please create a new report on Developer Community or GitHub with your current version information, steps to reproduce, and relevant error messages or log files if you are hitting an issue that looks similar to this resolved bug and you do not yet see a matching new report.

Related Links:

Description Yuri Tikhomirov 2013-11-13 18:48:41 UTC
The situation when the problem is catched is when some NSDictionary contains a key-value pair where key and value equals and are strings.

Let's imagine there's a NSDictionary represented with following json:

    myNsDict = {"Hello": "world", "Bye": "Bye"}

Let's get values:

string hello = myNsDict["Hello"] as NSString; => "world"
string bye = myNsDict["Bye"] as NSString; => null

    (myNsDict["Bye"] as NSString).Handle => IntPtr.Zero
    (myNsDict["Bye"] as NSString).disposed => true (can be seen in watch during debug)


    string bye2 = (myNsDict[new NSString("Bye")] as NSString) => "Bye"

The reason is probably related to some Apple's new mechanisms in iOS7 to cache NSString (the problem is not met under iOS6, or maybe very rarely).

As we may find in getter of public virtual NSObject this [string key], a key is 'casted' to NSString (nSString = new NSString (key)), then ObjectForKey(nSString) is called and after the result is get, finally nSString is Dispose()'ed.

I think this causes the result object to be disposed / collected too.
Comment 1 Rolf Bjarne Kvinge [MSFT] 2013-11-13 19:03:08 UTC
I tried this code, and it never printed null:

	var nsDict = NSDictionary.FromObjectsAndKeys (new object [] { "world", "Bye" }, new object [] { "Hello", "Bye" }, 2);
	var hello = nsDict ["Hello"] as NSString;
	var bye = nsDict ["Bye"] as NSString;
	Console.WriteLine ("Hello: {0} bye: {1}", hello, bye);

Could you please attach a complete test project we can try out?
Comment 2 Yuri Tikhomirov 2013-11-14 07:19:31 UTC
Created attachment 5425 [details]
An example project reproducing the problem.
Comment 3 Yuri Tikhomirov 2013-11-14 07:53:19 UTC
Created attachment 5426 [details]
Watch results in my project
Comment 4 Yuri Tikhomirov 2013-11-14 07:55:15 UTC
Created attachment 5427 [details]
Watch results in my project
Comment 5 Yuri Tikhomirov 2013-11-14 08:25:16 UTC
Created attachment 5429 [details]
A project that uses Resources class with static instance

The NSDictionary reference is stored in Resources class and is loaded from bundle.
Comment 6 Yuri Tikhomirov 2013-11-14 08:27:29 UTC
Rolf, I've attached the project. Some comments.

In a large project I'm working on, getting the value happens in main thread.
But here it works in a separate thread. And suddenly when I try to invoke
getting in main thread, it doesn't reproduces...

It also won't be reproduced without the line in cycle:

    var alloc = new byte [ random.Next(1024, 1024*100) ]; 

There's a screenshot of my project's watch results.

ps. Unfortunatelly, after several attempts,  I don't know how to exactly
reproduce the thing in main thread. Sorry for that. I've attached a test
project that gives some kind of a look on how it is implemented in my app (I
mean Resources class).
Comment 7 Rolf Bjarne Kvinge [MSFT] 2013-11-14 08:37:18 UTC
I'm able to reproduce using the project in comment 2.
Comment 8 Rolf Bjarne Kvinge [MSFT] 2013-11-14 09:35:54 UTC
This is probably a duplicate of bug #7723.
Comment 9 Rolf Bjarne Kvinge [MSFT] 2013-11-14 09:43:10 UTC

*** This bug has been marked as a duplicate of bug 7723 ***