Пережеванные выкладки программиста

или же трудные будни ленивца-скурпулезы

Previous Entry Share Next Entry
Работа с памятью в Objective-C. Аналогия с C/C++. Часть 2.
mylogo, xydan, xydan83_logo
xydan

Garbage Collector (GB)

Это особенный режим управления памятью, основанный на переодическом запуске сборщика муссора. Мы так же как и в предыдущем варианте выделяем память, но не освобождаем ее. За нас пямять освобождает сборщик мусора. Но к сожалению он имеет несколько огромных недостатков:

  1. Его должны поддерживать все без исключения используемые библиотеки. Скажем, если ARC позволяет использовать не-ARC подход, то с GB такое не пройдет, либо программа и все ее библиотеки полностью поддерживают этот метод управления памятью, либо программа просто не будет скомпилированна;

  2. Данный недостаток думаю относиться ко всем сборщикам мусора. Сборка мусора - это достаточно ресурсоемкая задача, она требует как дополнительной памяти, так и достаточно много процессорного времени. И каждый раз, когда программа будет вызывать сборщик мусора, выполнение программы в это время будет сопровождаться достаточно заметным поддотмаживанием. Конечно степень тормознутости будет зависеть от конфигурации MAC.

Если подвести итог вышесказанному, то я бы не советовал использоват в своих программах GB. Наилучшая альтернатива - это всетаки ARC.




/*

Пример работы с объектами в C/C++ по сравнению с Obj-C

Для тех кто не работал с VCL. AnsiString - это класс для работы

со строковыми данными (аналогично std::string).

*/

//---------------------------------------------------------------------------

#include <vcl.h>

#include <stdio.h>

#pragma hdrstop

#include <tchar.h>

//---------------------------------------------------------------------------

using namespace std;

#pragma argsused

int _tmain(int argc, _TCHAR* argv[])

{

//Создаю новый объект str1

AnsiString *str1 = new AnsiString("String 1\r\n");

//Создаю указатель str2 и принимаю адресс на объект str1. В итоге оба указателя

//указывают на один и тот же объект

AnsiString *str2 = str1;//Легкая копия (assign)

//Создаю новый объект с новой строкой и записываю адресс в существующий указатель

//str1, который указывает на совершенно новый объект. В итоге:

//str1 - указывает на новый объект;

//str2 - указывает на предыдущий объект

str1 = new AnsiString("String 2\r\n");

//Создаю новый объект str3, пустой.

AnsiString *str3 = new AnsiString();

//Копирую содержимое одного объекта в другой. В итоге один объект указывает

//на другой

*str3 = *str1;//Полная копия объекта (copy)

//Выводим все объекты на экран сишными функциями

printf(str1->c_str());

printf(str2->c_str());

printf(str3->c_str());

//Поскольку каждый из указателей сейчас укзаывает на совершенно разные объекты

//то надо все подчистить перед выходом. Аналогично (release).

delete str1; //[str1 release]

delete str2; //[str2 release]

delete str3; //[str3 release]

/*Стоит заметить, что в чистом си и плюсах нет аналога retain, такой счетчик

необходимо реализовывать самому или использовать специальные библиотеки

Соответственно реализации autorelease тоже нет, но возможно все это

поддерживается в сторонних библиотеках по работе с памятью*/

//Так сделаем задержку, чтобы консоль сразу не пропала.

getchar();

return 0;

}

//---------------------------------------------------------------------------

Из рисунка выше видно, что все переменные указателей имеют новые адресса, но объекты не потеряны, так как никакой объект не повис в «воздухе».


Вот так выглядит результат выполнения программы.

/*

Пример работы с объектами с Obj-C

*/

//

// main.m

// CommandLineTest

//

//

#import <Foundation/Foundation.h>

#import <Foundation/NSString.h>

s

int main (int argc, const char * argv[])

{

@autoreleasepool {

//Создаю новый объект со строкой String1 и передаю адресс в переменную указателя str1

NSString *str1 = @"String1\r\n";

//Копирую адресс указателя на объект из str1 в str2. Счетчик использования объектов не увеличивается

NSString *str2 = str1;

//NSString *str2 = [str1 assign];//Легкая копия (аналогична *str2 = str1), но не все классы наследуемые от NSObject этот метод реализуют

str1 = @"String2\r\n";//В этой строчке уазатель str1 будет указывать совершенно на другой объект

//Копирую объект из str1 в str3. Создается совершенно новый объект и данные из объекта str1 копируются в str3 средствами реализация метода copy в классе NSString.

NSString *str3 = [str1 copy];//Полная копия вродебы - но тут хочу открыть фишку - все НЕИЗМЕНЯЕМЫЕ (imutable) объекты в стандартных фреймворках как правило не копируются, а просто вызывается метод retain.

//Теперь создаем новый указатель и копируем туда указатель объекта находящегося по адрессу располагающемося в указателе str2 с увеличением счетчика использования объектов

NSString *str4 =[str2 retain];

//А теперь создадим изменяемый объект и заодно сделаем его автоудаляемым.

NSMutableString *strMut = [[[NSMutableString alloc]init]autorelease];

//Добавим в него новую строчку..

[strMut appendFormat:@"String Mutable\r\n"];

// А тут у нас уже происходит полное копирование с созданием нового объекта

NSMutableString *strMut2 = [strMut copy];

//Выведем все на экран

printf("%s",[str1 UTF8String]);

printf("%s",[str2 UTF8String]);

printf("%s",[str3 UTF8String]);

printf("%s",[str4 UTF8String]);

printf("%s",[strMut UTF8String]);

printf("%s",[strMut2 UTF8String]);

//Удаляем объекты из памяти.

[str1 release];

[str2 release];

[str3 release];

[str4 release];

//[strMut release]; - Если раскомментируем - то будет ошибка при очистке пула

[strMut2 release];//А вот так все ок...объект должны сами удалить.

}//Вот тут у нас очищается пул autorelease (аналогично [pool drain];).

return 0;

}

Из рисунка выше можно видеть, что при копировании mutable объекта, создается новый объект (strMut и strMut2). А вот при копировании объекта immutable ( str1 и str3) видно, что объект просто скопировал указатель (взял объект во владение методом retain), в итоге адреса переменные указателей хранят на один и тот же объект.



Вот так выглядит результат выполнения программы.

Полезные ссылки, где можно почитать про работу с памятью на уровне объектов:
http://ru.wikipedia.org/wiki/Objective-C - куда же без вики)) Но на мой взгляд там достаточно грамотно описаны вещи по работе с объектами;
http://www.imaladec.net/story/memory_management - Управление памятью;
http://www.imaladec.net/story/arc - инфа про ARC;  
http://pyobjc.ru/2008/07/19/vvedenie-v-objective-c/ - неплохая обобщенная статья про Objective-C; 


Спасибо за внимание:)

P.s Надеюсь моя статья окажется полезной. То, что я описывал, это по сути мой пройденный этап освоения Obj-C на личном опыте. В случае нахождения каких либо ошибок или неточностей, просьба сообщить мне об этом) 



?

Log in

No account? Create an account