Notice (2018-05-24): bugzilla.xamarin.com is now in
Please join us on
Visual Studio Developer Community and in the
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
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.
Since I started profiling my MonoTouch app, I've discovered that it's extremely leaky. Practically everything I allocated wasn't getting collected.
After considerable time and effort I was able to whittle down my code to a small sample that reproduces the issue. Running the sample below in the latest stable MonoTouch (6.0.4 at the time of this writing) causes memory to endlessly leak until the app crashes.
This repros in all situations I've tested it in: Both in the simulator and on the device, and both with and without SGen check-box checked, and both with and without the referencing counting extension check-box checked.
class WamlEntryPoint : UIApplicationDelegate
static void Main(string args)
UIApplication.Main(args, null, "AppDelegate");
private UIWindow MainWindow;
private Screen _rootInstance;
private UINavigationController _navigationController;
private UILabel _lbl;
public override void FinishedLaunching(UIApplication app)
//Create the UIWindow and UINavigationController
MainWindow = new UIWindow(UIScreen.MainScreen.Bounds);
MainWindow.RootViewController = _navigationController = new UINavigationController();
//Create an instance of Screen and push it
_rootInstance = new Screen();
//Create a label for reporting the memory usage
_lbl = new UILabel();
_lbl.Frame = UIScreen.MainScreen.Bounds;
//Kick off an automated loop after a second
/// Creates a new screen, pushes it on the nav controller and then immediately pops it off. Then just report total memory used.
var newScreen = new Screen();
//This is the magic that demonstrates the GC bug - some circular relationship of objects.
var foo = new Foo();
foo.Parent = newScreen;
//Report memory used
this._lbl.Text = "Total Memory Used = " + GC.GetTotalMemory(true);
//Do it again in half a second
public class Screen
public UIView ScreenView;
public MyUIViewControler ViewController;
ViewController = new MyUIViewControler(this);
ScreenView = new UIView();
public class MyUIViewControler : UIViewController
byte buffer = new byte; //artificially use more memory so that we can easily see if this is being collected when we call GC.GetTotalMemory()
public Screen Screen;
public MyUIViewControler(Screen s)
Screen = s;
public override void LoadView()
this.View = Screen.ScreenView;
public class Foo
public Screen Parent;
public MyUIView FoosView;
FoosView = new MyUIView(this);
public class MyUIView : UIView
private Foo _foo;
public MyUIView(Foo parent)
_foo = parent;
Created attachment 2847 [details]
Attaching the same code that's pasted in the bug since bugzilla seems to insert newlines on long lines.
This is an unfortunate side-effect of having to co-exist with ObjectiveC's reference counting.
I have explained this somewhat here: http://stackoverflow.com/a/13059140/183422 - the sample there isn't identical to yours but it is the same root cause. In short: ObjectiveC keeps the tree of objects in top->bottom order from being freed, and the managed GC keeps the tree of objects in bottom->top order from being freed.
One way to fix this in your case is to use weak gchandles in the bottom->top line (so Foo would create a weak gchandle for its Parent property, and MyUIView would create a weak gchandle for its _foo property).
We have plans to improve this scenario (probably by better tools to detect this and help you understand what's going on), but it's a complex subject so it will take some time.