Обновление 2: Apple ответила на мой отчет об ошибке: «Мы считаем, что эта проблема была устранена в iOS 4.2 b1 (8C5091e). Пожалуйста, сообщите нам, продолжаете ли вы испытывать эту проблему с недавно выпущенное программное обеспечение, обновив этот отчет об ошибках. " Я думаю, это признает, что проблема в их коде, а не в моем. Я обновлю результаты, когда я или кто-то из моих знакомых сможет обновить это, чтобы попробовать это.
Обновление: Мой коллега воспроизвел проблему на другом компьютере и iPad, так что это, вероятно, не просто причуды с моей настройкой.
Это странно.
Недавно я заметил, что инструмент Leaks сообщает об утечках памяти в моем приложении, и НИКОГДА не указывает на мой код в трассировке стека, только на различные встроенные библиотеки. К счастью (?) Я смог удалить практически все и в результате получил глупо простой проект, который запускает такое поведение каждый раз, по крайней мере, на моей машине. Просто чтобы быть уверенным, я запустил новый проект, прошел эти шаги и столкнулся с тем же поведением.
Я использую Xcode 3.2.4 и Instruments 2.7 на iPad (не 3G) с iOS 3.2.2.
- Я запускаю новое «Окно-приложение», нацеленное на iPad и устанавливающее флажок «Использовать базовые данные для хранения», которое генерирует набор средств доступа к свойствам для удобного компонента Core Data в делегате приложения. (Я могу опубликовать их в случае необходимости, но я не изменяю их вообще из того, что они генерируют.)
- Я редактирую модель, добавляя одну сущность, называемую «Пользователь», без других атрибутов или связей.
- Я добавляю
-(void)loadUser
метод к делегату приложения и вызываю его в -(BOOL)application:didFinishLaunchingWithOptions:
Вот единственный бит настроенного кода, как описано выше.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
[window makeKeyAndVisible];
[self loadUser];
return YES;
}
- (void)loadUser {
NSManagedObjectContext *moc = self.managedObjectContext;
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"User"
inManagedObjectContext:moc];
[fetchRequest setEntity:entityDescription];
NSError *error;
NSLog(@"counting users");
NSUInteger count = [moc countForFetchRequest:fetchRequest error:&error];
if (count == NSNotFound) {
NSLog(@"error: %@", error);
} else if (count == 0) {
NSLog(@"creating user");
// make a user
NSManagedObject *object = [[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:moc];
if (![moc save:&error]) {
NSLog(@"error: %@", error);
}
[object release];
}
NSLog(@"fetching user");
NSArray *results = [moc executeFetchRequest:fetchRequest error:&error];
if (results) {
NSLog(@"results: %@", results);
} else {
NSLog(@"error: %@", error);
}
[fetchRequest release];
}
Подсчет и вставка есть, потому что утечки не происходит, если нет данных, и это самый простой способ, которым я знаю, "заполнить" их. Логи там только для проверки работоспособности; они могут быть удалены, и утечки все еще обнаруживаются.
Этот код кажется мне совершенно безобидным. Когда я запускаю его на устройстве с утечками, я позволяю ему автоматически проверять наличие утечек через несколько секунд, и каждый раз, когда возникает следующее:
Это не происходит на симуляторе, но всегда происходит на устройстве.
Очевидно, что здесь происходит что-то странное. JavaScriptCore? Откуда это входит в вещи? Вот трассировка стека для одного из них:
16 libSystem.B.dylib thread_assign_default
15 libSystem.B.dylib _pthread_start
14 WebCore RunWebThread(void*)
13 JavaScriptCore JSC::initializeThreading()
12 libSystem.B.dylib pthread_once
11 JavaScriptCore JSC::initializeThreadingOnce()
10 JavaScriptCore WTF::initializeThreading()
9 JavaScriptCore WTF::initializeMainThread()
8 JavaScriptCore WTF::initializeMainThreadPlatform()
7 libobjc.A.dylib objc_msgSend_uncached
6 libobjc.A.dylib _class_lookupMethodAndLoadCache
5 libobjc.A.dylib lookUpMethod
4 libobjc.A.dylib prepareForMethodLookup
3 libobjc.A.dylib _class_initialize
2 libobjc.A.dylib _fetchInitializingClassList
1 libobjc.A.dylib _objc_fetch_pthread_data
0 libobjc.A.dylib _calloc_internal
Ни одна из трассировок стека не упоминает мой код. Я не делаю явной многопоточности. Там нет просмотра веб-страниц или что-либо еще, что связано с JavaScript. На моей машине я последовательно получаю этот результат, просто следуя инструкциям выше. Я удалил и переустановил приложение на iPad. Я перезапустил Xcode, перезапустил iPad и перезагрузил компьютер. То же самое дело.
Мои вопросы:
Могут ли другие люди воспроизвести ту же проблему? (редактировать: один человек имеет, на другом компьютере и iPad)
Если нет, то, думаю, это странная проблема с моей конфигурацией, и я хотел бы знать, что я могу сделать, чтобы это исправить.
Если так, что, черт возьми, происходит? Мой код виноват? Разве это не то, как я должен получать объекты? Это ложный положительный результат от утечек или ошибка в базовых данных? Есть ли обходной путь? Мне бы очень хотелось иметь возможность точно определять утечки, и это затрудняет это.