为什么即使使用非常简单的应用程序,MonoTouch仍会导致大量内存泄漏(据《仪器》报道)? [英] Why does MonoTouch cause lots of memory leaks (as reported by Instruments) even with very simple Apps?
问题描述
我正在使用Instruments运行一个非常基本的测试应用程序,它发现了很多内存泄漏!既然我知道当将应用程序提交到iTunes时,苹果的家伙会检查内存泄漏,所以我想调查这个问题.
I'm running a very basic test App with Instruments, and it finds a lot of memory leaks! Since I know that Apple guys perform checks for leaked memory when an App is submitted to iTunes, I would like to investigate the problem.
我的环境:Mac OS X 10.6.6上具有MonoTouch 3.2.4的MonoDevelop 2.4.2,面向运行iOS 4.2.1的iPad.
My environment: MonoDevelop 2.4.2 with MonoTouch 3.2.4 on Mac OS X 10.6.6, targeting an iPad running iOS 4.2.1.
我的测试应用程序仅显示了一个TableView,其中填充了50个字符串的列表,并按其起始字母分组.
My test App simply shows a TableView populated with a list of 50 strings, grouping them by their starting letter.
重现该问题的步骤:使用MonoDevelop创建一个新的基于iPad Window的项目",使用Interface Builder打开MainWindow.xib文件,在该窗口上放置一个新的TableView并创建其出口(名为"tview")以AppDelegate类. 然后在Main.cs中输入以下代码:
Steps to reproduce the problem: create a new "iPad Window-based Project" with MonoDevelop, open the MainWindow.xib file with Interface Builder, place a new TableView onto the window and create its outlet (named "tview") to the AppDelegate class. Then enter the following code in Main.cs:
using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
namespace SimpleTable
{
public class Application
{
static void Main (string[] args)
{
UIApplication.Main (args);
}
}
public partial class AppDelegate : UIApplicationDelegate
{
private List<string> _names;
public override bool FinishedLaunching (UIApplication app, NSDictionary options)
{
_names = new List<string> { "Smith", "Jones", "Williams", "Brown", "Taylor",
"Davies", "Wilson", "Evans", "Thomas", "Johnson",
"Roberts", "Walker", "Wright", "Robinson", "Thompson",
"White", "Hughes", "Edwards", "Green", "Hall",
"Wood", "Harris", "Lewis", "Martin", "Jackson",
"Clarke", "Clark", "Turner", "Hill", "Scott",
"Cooper", "Morris", "Ward", "Moore", "King",
"Watson", "Baker", "Harrison", "Morgan", "Patel",
"Young", "Allen", "Mitchell", "James", "Anderson",
"Phillips", "Lee", "Bell", "Parker", "Davis" };
tview.Source = new MyTableViewSource(_names);
window.MakeKeyAndVisible ();
return true;
}
private class MyTableViewSource : UITableViewSource
{
private List<string> _sectionTitles;
private SortedDictionary<int, List<string>> _sectionElements = new SortedDictionary<int, List<string>>();
public MyTableViewSource(List<string> list)
{
// Use LINQ to find the distinct set of alphabet characters required.
_sectionTitles = (from c in list select c.Substring(0, 1)).Distinct().ToList();
// Sort the list alphabetically.
_sectionTitles.Sort();
// Add each element to the List<string> according to the letter it starts with
// in the SortedDictionary<int, List<string>>.
foreach (string element in list)
{
int sectionNum = _sectionTitles.IndexOf(element.Substring(0, 1));
if (_sectionElements.ContainsKey(sectionNum))
{
// SortedDictionary already contains a List<string> for that letter.
_sectionElements[sectionNum].Add(element);
}
else
{
// First time that letter has appeared, create new List<string> in the SortedDictionary.
_sectionElements.Add(sectionNum, new List<string> { element });
}
}
}
public override int NumberOfSections(UITableView tableView)
{
return _sectionTitles.Count;
}
public override string TitleForHeader(UITableView tableView, int section)
{
return _sectionTitles[section];
}
public override int RowsInSection(UITableView tableview, int section)
{
return _sectionElements[section].Count;
}
public override UITableViewCell GetCell(UITableView tableView, NSIndexPath indexPath)
{
string kCellIdentifier = "mycell";
UITableViewCell cell = tableView.DequeueReusableCell(kCellIdentifier);
if (cell == null)
{
// No re-usable cell found, create a new one.
cell = new UITableViewCell(UITableViewCellStyle.Default, kCellIdentifier);
}
string display = _sectionElements[indexPath.Section][indexPath.Row];
cell.TextLabel.Text = display;
return cell;
}
public override void RowSelected(UITableView tableView, NSIndexPath indexPath)
{
string display = _sectionElements[indexPath.Section][indexPath.Row];
showAlert("RowSelected", "You selected: \"" + display + "\"");
// Prevent the blue 'selection indicator' remaining.
tableView.DeselectRow(indexPath, true);
}
private void showAlert(string title, string message)
{
using (var alert = new UIAlertView(title, message, null, "OK", null))
{
alert.Show();
}
}
}
}
}
我已经在设备上执行了以下测试:
I have performed the following tests on the device:
-
评论
commented out
public override string TitleForHeader(UITableView tableView, int section)
程序,从Instruments内启动的App:发现一个泄漏;即使测试一个空的应用程序,似乎总是存在这种泄漏!
procedure, launched App from within Instruments: a single leak is found; it seems that this leak is ALWAYS present, even when testing an empty App!
Test 1 Instruments screenshot
未注释
public override string TitleForHeader(UITableView tableView, int section)
从Instruments内启动的应用程序的过程:发现大量泄漏,并且在上下滚动表和/或选择任何行时,泄漏的数目会增加.
procedure, launched App from within Instruments: a lot of leaks are found, and their number grows up when scrolling the table up and down and/or selecting any row.
Test 2 Instruments screenshot
取代了
return _sectionTitles[section];
声明
public override string TitleForHeader(UITableView tableView, int section)
过程
return "Test Header…";
(因此使用常量字符串):与测试n.2中的相同!
(thus using a constant string): the same as in test n.2!
MonoTouch是否出错了,还是我忘记了一些必不可少的东西?如果即使这样一个简单的应用程序在运行几分钟后仍会产生数百个内存泄漏,那么真正的(以及更复杂的)应用程序会发生什么?
Is MonoTouch bugged or am I forgetting something essential? If even such a simple App generates hundreds of memory leaks when running for a few minutes, what could happen with a real (and more complex) App?
我已经在网上进行了广泛的搜索,但是没有找到有关此问题的重要文章...任何贡献将不胜感激.
I have searched the web extensively but I haven't found any significant post about this problem... any contribution will be greatly appreciated.
推荐答案
仪器尚未完全理解monotouch和mono vm分配和管理内存的方式.苹果没有为此拒绝任何申请.如果您认为某个特定的漏洞是泄漏的,请在 http://monotouch.net/的monotouch bugtracker中提出问题.支持
The way monotouch and the mono vm allocates and manages memory isn't fully understood by instruments. Apple has not rejected any applications for this. If you have a specific bug that you think is a leak please file an issue in the monotouch bugtracker at http://monotouch.net/Support
话虽如此,我查看了您的屏幕截图,并确实发现了可能发生的1个16字节泄漏,以及第二个屏幕截图中的泄漏,并针对即将推出的monotouch 4进行了修复.
That being said, I looked at your screenshots and did find 1 16-byte leak that could happen, and the leak in your second screenshot, and fixed that for the upcoming monotouch 4.
这篇关于为什么即使使用非常简单的应用程序,MonoTouch仍会导致大量内存泄漏(据《仪器》报道)?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!