Блог О пользователеiphonesdk

Регистрация

 

Теги

_isnan _t apple automation autorelease pool bar bash bug c++ cellforrowatindexpat h cgimage chflags cocoa condition const contentinset contentsize cpp.cpp dealloc debug debugger destructor exc_bad_access exist finger piano share gcc header headers herb sutter interface builder ios ios 5.0 ios 6 ipad iphone iphone os iphone sdk ipod ipod touch isnan junior leader line link linker linux mac os mac os x 10.7 man member memory microsoft visual studio multithread multithreading navigation bar nil nsautoreleasepool nslog nsstring nsthread nstimer nszombieenabled objcpp.cpp objective c objective-c out of memory phread posix pthread pthread_attr_setstac ksize quartz regex regular expressions release rename rotate script senior setevent shell sleep stack stack size static lib status bar std::toupper stricmp team leader template class temporary files thread tinyxml uiactivityindicator uicollectionview uigraphicspopcontext uigraphicspushcontex t uiimage uiscrollview uitableview uitableviewcell unix upgrade current target for ipad validate variables win32 windows www.odesk.com xcode xcode 4.2 xcode-проект xcodebuild xcodeproj xml xml document xml parser yamaha автоматизация автоматически алёна c++ алёна сагалаева андрей александреску антипаттерны банда четырёх бертран мейер библиотеки быстрая разработка программ временные файлы вывод текста герб саттер гигантская гради буч дедлок дерево проекта деструктор джоэл спольски директория дополнительный поток защита знание языка c++ изображение исходник каталог квалификация коллективный проект компилятор компиляция константная константные контрол копировать линкование линковка макроопределение мембер многопоточность настройка несколько библиотек в одном проекте несколько либ ооп основной поток падение память паттерны проектирования переименовать переполнение переполнение стека повернуть получить путь к папке портирование поток проблемы с отладчиком программирование программист проект размер текста разработчик рефакторинг роберт лафоре роберт мартин си++ скрипт смещение контрола ссылки статическая библиотека статические библиотеки статические либы стек стив макконел странности отладчика утечки памяти файл фредерик брукс функция человеко-лет человеко-месяц член член класса шаблонный класс электронные книги электронные читалки

1 |2 |3 |4 |5
 

Как выяснить причину EXC_BAD_ACCESS в Xcode


Нашёл интересную статью (на английском) на http://www.codza.com/how-to-debug-exc_bad_access-on-iphone (там это приводится с рисунками и комментариями читателей).

НАЧАЛО ЦИТАТЫ.

EXC_BAD_ACCESS. Debugging this one is on par with figuring out why the wife says “not tonight, honey.” And they are equally unfortunate situations.

Let’s see what we can do about EXC_BAD_ACCESS.

EXC_BAD_ACCESS happens when a message is sent to an object that has already been released. By the time the error is caught, the call stack is usually gone especially if dealing with multiple threads.

How nice would it be to keep a dummy around after the object is released that could stop execution, tell us what message was sent and show us the call stack… well, there’s a way to do just that.

If you set the NSZombieEnabled environment variable, the Objective C runtime will leave a dummy object behind for every deallocated object. When the zombie object is called, execution stops and you can see the message that was sent to the object and the call stack that tells you where the message came from (it doesn’t tell you where you over released the object, but knowing where the object is called from should get you pretty close to the problem.)

To set this variable, go to the info panel of the executable in xcode, and create a new environment variable in the arguments tab by clicking the plus sign in the lower left corner of the window. Name the variable NSZombieEnabled, type YES for the value and make sure that the checkbox is selected.
set NSZombieEnabled variable

set NSZombieEnabled variable

Go ahead and run your program now (in debug mode, because you need the stack information.) When the over released object is accessed, you get an error message similar to this (xcode debug view):

2009-03-30 02:30:36.172 ninjaJumper[3997:20b] *** -[GameLayer retain]: message sent
to deallocated instance 0x59bf670

This shows the class of the object (GameLayer) and the message sent (retain).

Let’s take a look at the stack now:
call stack

call stack

The methods printed in bold are in your code, the others are in some other API. Here you can see that the object was accessed from [Director touchesBegan:withEvent], where an array was copied (most likely the over released object was in the array.)

This information should get you pretty close to the problem.

Once the problem is fixed, make sure that the NSZombieEnabled variable is disabled. You don’t need to delete it, but make sure that the checkbox is unchecked:
NSZombie disabled

NSZombie disabled

Now about the wife. Good luck there. Try a box of chocolate or load the dishwasher for a couple days.

КОНЕЦ ЦИТАТЫ.

К СОЖАЛЕНИЮ, ДАННЫЙ СОВЕТ ПОЗВОЛЯЕТ ОТСЛЕЖИВАТЬ ИМЕНА Objective C КЛАССОВ. Я ТОЛЬКО ЧТО СДЕЛАЛ ТЕСТОВОЕ ПРИЛОЖЕНИЕ, В КОТОРОМ ПОЛЕЗНЫЕ ОТЛАДОЧНЫЕ СООБЩЕНИЯ ВЫВОДЯТСЯ В КОНСОЛЬ ТОЛЬКО КАСАЕМО Objective C КЛАССОВ:


TestClass *testObj = [[TestClass alloc] init];
[testObj release]; // уничтожили объект перед попыткой использования
[testObj printMsg];

В этом случае в консоль будет выводиться информация
2010-04-28 13:02:08.030 ZombieTest[1353:207] *** -[TestClass printMsg]: message sent to deallocated instance 0x3924880)


В случае же с C++ классом:

TestCppClass *tcpp = new TestCppClass();
delete tcpp;
tcpp = 0;
tcpp- >PrintMsg(); // удивительно, но это работает (на экран выводится тестовое сообщение, так как вероятно функция-член класса способна работать и без создания объекта - ЭТО ЧТО, ОЧЕРЕДНОЙ БАГ Xcode?)
delete tcpp; // тем не менее здесь код спотыкается, так как пытаемся уничтожить объект повторно

в консоль выводится то же самое что и без применения совета из приведённой статьи):
2010-04-28 13:04:45.242 ZombieTest[1476:207] TestClass --- printMsg
ZombieTest(1476,0xa0a7b4e0) malloc: *** error for object 0x3917160: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug

 

Что делать, если в Xcode-отладчике невозможно переключиться на другой поток


Лично у меня получается переключиться между потоками, как только я нажму Pause-кнопку (т.е. остановлю приложение). По крайней мере можно увидеть, что происходило в тот момент в разных потоках.

Нашёл некоторое объяснение на http://www.cocoabuilder.com/archive/xcode/248374-debug-problem-in-multithreaded-environment-in-xcode.html

Там такой ответ и совет, надеюсь, программисты умеют читать по-английски:

Sometimes this happens because of the same reason that the backtrace
stack gets bumped off the top of the screen. This is a known problem
that we are investigating. Try toggling the debugger layout (using
the Toggle Debugger Layout command) or deleting the .mode1 file
in your Project's bundle.

 
 
 

Как изменить размер стека потока средствами pthread-функций


pthread_attr_t threadAttr;
pthread_t tid_;  
       
// initialize the thread attribute
assert(!pthread_attr_init(&threadAttr));

// Set the stack size of the thread (for example 2 Mb)
assert(!pthread_attr_setstacksize(&threadAttr, 1024*1024*2));
                                                               
 size_t stackSize;                                                   
   
// Проверим, точно ли у нас размер стека 2 Mb
assert(!pthread_attr_getstacksize(&threadAttr, &stackSize));   
printf("The stack size is %d. ***\n", (int) stackSize);

// Создаём поток с заданным размером стека                   
assert(!pthread_create(&tid_, &threadAttr, thread_func, function_));

// подчистим за собой
assert(!pthread_attr_destroy(&threadAttr));

 

Интересные материалы для C++ программистов в блоге "Алёна C++"


Очень интересные материалы найдут для себя C++ программисты в блоге Алёны Сагалаевой:
http://alenacpp.blogspot.com/

Например, я только что нашёл интересный пример о константных ссылках (в свою очередь Алёна нашла этот пример в блоге знаменитого Герба Саттера http://herbsutter.spaces.live.com/blog/cns!2D4327CC297151BB!378.entry):

ЦИТИРУЮ ИЗ БЛОГА АЛЁНЫ (http://alenacpp.blogspot.com/2008/01/const.html):

Возможно, самый важный const

Герб Саттер у себя в блоге рассказывает про интересный случай с использованием const.

Краткий пересказ для ленивых.


string f() { return "abc"; }

void g() {
const string& s = f();
cout < < s < < endl; // можно ли использовать временный объект?
}


Код несколько напрягает. Создается ссылка на временный объект. Но тем не менее, с кодом все в порядке. Почему так? Потому что в С++ явно специфицировано, что если привязать временный объект к ссылке на const в стеке, то жизнь временного объекта будет продлена. Теперь он будет жить столько, сколько живет константная ссылка на него. В приведенном примере все валидно, время жизни s заканчивается с закрывающей фигурной скобкой.

Это все относится только к объектам в стеке. На члены класса это не действует.

С++ это специфицирует, а как оно в реальности, работает? Герб проверил в нескольких компиляторах, нормально, практически во всех работает.

Легким движением руки убираем const...

string f() { return "abc"; }

void g() {
string& s = f(); // все еще нормально?
cout < < s < < endl;
}
И получаем невалидный код, наличие const'а тут важно. Правильный компилятор выдаст ошибку на этапе компиляции.

И есть еще момент с вызовом деструктора.
Derived factory(); // construct a Derived object

void g() {
const Base& b = factory(); // здесь вызов Derived::Derived
// … используем b …
} // здесь вызывается Derived::~Derived напрямую
//-- а не Base::~Base + virtual dispatch!
Ссылки по теме:
Использование const. Часть 1.
Использование const. Часть 2.

КОНЕЦ ЦИТАТЫ

 

Принципы Agile Software Development


Что такое Принципы Дизайна Программного Обеспечения?

Принципы дизайна ПО представляют набор правил, который помогает избежать плохого дизайна. Принципы дизайна объединены Робертом Мартином, кто собрал их в "Agile Software Development: Principles, Patterns, and Practices" (т.е. "Быстрая разработка ПО: Принципы, Паттерны и Практика"). Согласно Роберту Мартину есть 3 важные характеристики плохого дизайна, которые нужно избегать:
Жёсткость - это когда трудно что-либо изменять в коде, так как каждое изменение оказывает воздействие на слишком много других частей системы.
Хрупкость - когда вы делаете изменение, и это приводит к неожиданной поломке других частей системы.
Непереносимость - код трудно повторно использовать в другом приложении, потому что этот код невозможно освободить от имеющегося приложения.

Принцип Открытости-Закрытости (Open Close Principle или OCP)


Программные сущности такие как классы, модули и функции должны быть открыты для расширения, но закрыты для изменений.
OPC является основополагающим принципом. Вы можете обсуждать его, когда пишете ваши классы, чтобы быть уверенными в том, что когда вам будет нужно расширить поведение, вы не должны будете изменять класс, но можете расширять его. Подобный же принцип применим для модулей, пакетов и библиотек. Если у вас есть библиотека, состоящая из множества классов, то есть много причин для того, чтобы вы предпочитали расширение вместо изменения кода, который уже написан (ради обратной совместимости, возвращение к предыдущему тестированию и т.п.). Это причина, по которой мы должны быть уверены, что наши модули следуют Принципу Открытости-Закрытости. По отношению к классам Принцип Открытости-Закрытости может быть гарантированно полезен засчёт использования Абстрактных Классов и конкретных классов для реализации их поведения. Это будет вынуждать иметь Конкретные Классы в качестве расширяющих Абстрактные Классы вместо их изменения. Некоторые частные случаи этого принципа есть Шаблонный Паттерн и Стратегический Паттерн (Template Pattern and Strategy Pattern).

Принцип Инверсии Зависимостей (Dependency Inversion Principle)


Высокоуровеневые модули должны не зависеть от низкоуровневых модулей. Оба должны зависеть от абстракций.
Абстракции не должны зависеть от деталей. Детали должны зависеть от абстракций.
Принцип Инверсии Зависимостей (Dependency Inversion Principle) формулирует, что мы должны отделять высокоуровневые модули от низкоуровневых модулей, вставляя слой абстракции между высокоуровневыми классами и низкоуровневыми классами. Более того этот принцип инвертирует зависимости: вместо написания наших абстракций, основанных на деталях мы должны писать детали, основанные на абстракциях.

Инверсия Зависимостей или Инверсия Контроля являются более понимаемыми терминами если ссылаться на способ, которым эти зависимости реализованы. Классическим способом в ситуации, когда программный модуль (класс, фреймворк, ...) нуждается в каком-нибудь другом модуле, он инициализует и держит прямую ссылку на этот другой модуль. Это приводит к тому, что 2 модуля становятся туго спаренными. Для их разъединения первый модуль будет обеспечиваться хуком, т.е. крючком (свойство, параметр, ...) и внешний модуль контролирующий зависимости будет добавлять ссылку на второй модуль. Засчёт применения Инверсии Зависимостей модули могут быть легко изменяемы другими модулями всего лишь засчёт изменения модуля зависимостей. Фабрики и Абстрактные Фабрики могут быть использованы в качестве фреймворков зависимостей, однако они являются специализированными фрейморками для того, что известно под названием Инверсия Контрольного Контейнера (Inversion of Control Container).

Принцип Отделения Интерфейса (Interface Segregation Principle)


Клиенты не должны принуждаться к зависимости от интерфейсов, которые они не используют.

Этот принцип учит нас заботиться о том, как мы пишем наши интерфейсы. Когда мы пишем интерфейсы, мы должны позаботиться о добавлении только тех методов, которые там должны быть. Если мы добавляем методы, которые не должны быть там, тогда классы реализующие интерфейс будут должны реализовывать эти лишние методы так же как и остальные методы. Например, если мы создаём интрфейс, называемый Worker (Рабочий) и добавляем метод lunch break (обеденный перерыв), тогда все workers (рабочие) будут должны иметь реализацию этого лишнего метода. А что если рабочий оказался роботом?

В качестве умозаключения приходим к тому, что Интерфейсы содержащие методы, которые не специфичны для них, такие методы приводят к тому, что интерфейсы называют загрязнёнными или жирными. Мы должны избегать создания таких интерфейсов.


Принцип Единственной Ответственности (Single Responsibility Principle)


Класс должен иметь только одну причину для изменения.

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

Принцип Единственной Ответственности был введён Tom DeMarco в его книге "Structured Analysis and Systems Specification, 1979". Роберт Мартин реинтерпретировал эту концепцию и определил, что ответственность является причиной для изменения.


Принцип Замещения Лискоу (Liskov's Substitution Principle)


Производные типы должны быть способны полностью замещаться их базовыми типами.

Этот принцип есть всего лишь расширение Принципа Открытости-Закрытости в условиях поведения, означающего, что мы должны быть уверены, что новые производные классы являются расширением базовых классов без изменения их поведения. Новые производные классы должны быть способны заменять базовые классы без каких-либо изменений в коде.
Принцип Замещения Лискоу был введён на 1987 Conference on Object Oriented Programming Systems Languages and Applications, in Data abstraction and hierarchy.

Last Updated ( Thursday, 27 March 2008 )

Перевод на русский язык Мурата Джусупова

Оригинальный текст на английском языке взят из http://www.oodesign.com/design-principles.html

 

Знакомство с компилятором GCC


Средствами, традиционно используемыми для создания программ для открытых операционных систем, являются инструменты разработчика GNU. Сделаем маленькую историческую справку. Проект GNU был основан в 1984 году Ричардом Столлманом. Его необходимость была вызвана тем, что в то время сотрудничество между программистами было затруднено, так как владельцы коммерческого программного обеспечения чинили многочисленные препятствия такому сотрудничеству. Целью проекта GNU было создание комплекта программного обеспечения под единой лицензией, которая не допускала бы возможности присваивания кем-то эксклюзивных прав на это ПО. Частью этого комплекта и является набор инструментов для разработчика, которым мы будем пользоваться, и который должен входить во все дистрибутивы Linux.

 

Одним из этих инструментов является компилятор GCC. Первоначально эта аббревиатура расшифровывалась, как GNU C Compiler. Сейчас она означает – GNU Compiler Collection.

Создадим первую программу с помощью GCC. По сложившейся традиции первая программа будет просто выводить в консоли приветствие «Hello world!» – «Здравствуй Мир!».

Файлы с исходными кодами программ, которые мы будем создавать, это обычные текстовые файлы, и создавать их можно с помощью любого текстового редактора (например GEdit KWrite, Kate, а также более традиционные для пользователей Linux – vi и emacs). Помимо текстовых редакторов, существуют специализированные среды разработки со своими встроенными редакторами. Одним из таких средств является KDevelop. Интересно, что в нём есть встроенный редактор и встроенная консоль, расположенная прямо под редактором. Так что можно прямо в одной программе, не переключаясь между окнами, и редактировать код и давать консольные команды.

Создайте отдельный каталог hello. Это будет каталог нашего первого проекта. В нём создайте текстовый файл hello.c со следующим текстом:

#include < stdio.h >

 

int main(void)

{

printf("Hello world!\n");

return(0);

}

Затем в консоли зайдите в каталог проекта. Наберите команду

gcc hello.c

Теперь посмотрите внимательно, что произошло. В каталоге появился новый файл a.out. Это и есть исполняемый файл. Запустим его. Наберите в консоли:

./a.out

Программа должна запуститься, то есть должен появиться текст:

Hello world!

Компилятор gcc по умолчанию присваивает всем созданным исполняемым файлам имя a.out. Если хотите назвать его по-другому, нужно к команде на компиляцию добавить флаг -o и имя, которым вы хотите его назвать. Давайте наберём такую команду:

gcc hello.c -o hello

Мы видим, что в каталоге появился исполняемый файл с названием hello. Запустим его.

./hello

Как видите, получился точно такой же исполняемый файл, только с удобным для нас названием.

Флаг -o является лишь одним из многочисленных флагов компилятора gcc. Некоторые другие флаги мы рассмотрим позднее. Чтобы просмотреть все возможные флаги, можно воспользоваться справочной системой man. Наберите в командной строке:

man gcc

Перед вами предстанет справочная система по этой программе. Просмотрите, что означает каждый флаг. С некоторыми из них мы скоро встретимся. Выход из справочной системы осуществляется с помощью клавиши q.

Вы, конечно, обратили внимание, что, когда мы запускаем программу из нашего каталога разработки, мы перед названием файла набираем точку и слэш. Зачем же мы это делаем?

Дело в том, что, если мы наберём только название исполняемого файла, операционная система будет искать его в каталогах /usr/bin и /usr/local/bin, и, естественно, не найдёт. Каталоги /usr/bin и /usr/local/bin – системные каталоги размещения исполняемых программ. Первый из них предназначен для размещения стабильных версий программ, как правило,входящих в дистрибутив Linux. Второй – для программ, устанавливаемых самим пользователем (за стабильность которых никто не ручается). Такая система нужна,чтобы отделить их друг от друга. По умолчанию при сборке программы устанавливаются в каталог /usr/local/bin. Крайне нежелательно помещать что-либо лишнее в /usr/bin или удалять что-то оттуда вручную, потому что это может привести к краху системы. Там должны размещаться программы, за стабильность которых отвечают разработчики дистрибутива.

Чтобы запустить программу, находящуюся в другом месте, надо прописать полный путь к ней, например так:

/home/dima/projects/hello/hello

Или другой вариант: прописать путь относительно текущего каталога, в котором вы в данной момент находитесь в консоли. При этом одна точка означает текущий каталог, две точки – родительский. Например, команда ./hello запускает программу hello, находящуюся в текущем каталоге, команда ../hello – программу hello, находящуюся в родительском каталоге, команда ./projects/hello/hello – программу во вложенных каталогах, находящихся внутри текущего.

Есть возможность добавлять в список системных путей к программам дополнительные каталоги. Для этого надо добавить новый путь в системную переменную PATH. Но давайте пока не будем отвлекаться от главной темы. Переменные окружения – это отдельный разговор.

Теперь рассмотрим, что же делает программа gcc. Её работа включает три этапа: обработка препроцессором, компиляция и компоновка (или линковка).

Препроцессор включает в основной файл содержимое всех заголовочных файлов, указанных в директивах #include. В заголовочных файлах обычно находятся объявления функций, используемых в программе, но не определённых в тексте программы. Их определения находятся где-то в другом месте: или в других файлах с исходным кодом или в бинарных библиотеках.

Вторая стадия – компиляция. Она заключается в превращении текста программы на языке C/C++ в набор машинных команд. Результат сохраняется в объектном файле. Разумеется, на машинах с разной архитектурой процессора двоичные файлы получаются в разных форматах, и на одной машине невозможно запустить бинарник, собранный на другой машине (разве только, если у них одинаковая архитектура процессора и одинаковые операционные системы). Вот почему программы для UNIX-подобных систем распространяются в виде исходных кодов: они должны быть доступны всем пользователям, независимо от того, у кого какой процессор и какая операционная система.

Последняя стадия – компоновка. Она заключается в связывании всех объектных файлов проекта в один, связывании вызовов функций с их определениями, и присоединением библиотечных файлов, содержащих функции, которые вызываются, но не определены в проекте. В результате формируется запускаемый файл – наша конечная цель. Если какая-то функция в программе используется, но компоновщик не найдёт место, где эта функция определена, он выдаст сообщение об ошибке, и откажется создавать исполняемый файл.

Теперь посмотрим на практике, как всё это выглядит. Напишем другую программу. Это будет примитивнейший калькулятор, способный складывать, вычитать, умножать и делить. При запуске он будет запрашивать по очереди два числа, над которыми следует произвести действие, а затем потребует ввести знак арифметического действия. Это могут быть четыре знака: «+», «–», «*», «/». После этого программа выводит результат и останавливается (возвращает нас в операционную систему, а точнее – в командный интерпретатор, из которого мы программу и вызывали).

Создадим для проекта новую папку kalkul, в ней создадим файл kalkul.c.

#include < stdio.h >

 

int main(void)

{

float num1;

float num2;

char op;

 

printf("Первое число: ");

scanf("%f",&num1);

 

printf("Второе число: ");

scanf("%f",&num2);

 

printf("Оператор ( + - * / ): ");

while ((op = getchar()) != EOF)

{

if (op == '+')

{

printf("%6.2f\n",num1 + num2);

break;

}

else if(op == '-')

{

printf("%6.2f\n",num1 - num2);

break;

}

else if(op == '*')

{

printf("%6.2f\n",num1 * num2);

break;

}

else if(op == '/')

{

if(num2 == 0)

{

printf("Ошибка: деление на ноль!\n");

break;

}

else

{

printf("%6.2f\n",num1 / num2);

break;

}

}

}

 

return 0;

}

Итак, первым делом, как было сказано, выполняется препроцессинг. Для того, чтобы посмотреть, что на этом этапе делается, воспользуемся опцией -E. Эта опция останавливает выполнение программы на этапе обработки препроцессором. В результате получается файл исходного кода с включённым в него содержимым заголовочных файлов.

В нашем случае мы включали один заголовочный файл – stdio.h – коллекцию стандартных функций ввода-вывода. Эти функции и выводили на консоль нужный текст, а также считывали с консоли вводимые нами слова.

Введите следующую команду:

gcc -E kalkul.c -o kalkul.cpp

Полученному файлу мы дали имя kalkul.cpp. Откройте его. Обратите внимание на то, что он весьма длинный. Это потому что в него вошёл весь код заголовочного файла stdio.h. Кроме того, препроцессор сюда добавил некоторые теги, указывающие компилятору способ связи с объявленными функциями. Основной текст нашей программы виден только в самом низу.

Можете заодно посмотреть, какие ещё функции объявлены в заголовочном файле stdio.h. Если вам захочется получить информацию о какой-нибудь функции, можно поинтересоваться о ней во встроенном руководстве man. Например, если вам вдруг захочется узнать, что же делает таинственная функция fopen, можно набрать:

man fopen

Много информации также есть в справочной системе info.

info fopen

Можно поинтересоваться и всем заголовочным файлом сразу.

man stdio.h

info stdio.h

Посмотрим теперь следующий этап. Создадим объектный файл. Объектный файл представляет собой «дословный» перевод нашего программного кода на машинный язык, пока без связи вызываемых функций с их определениями. Для формирования объектного файла служит опция -c.

gcc -c kalkul.c

Название получаемого файла можно не указывать, так как компилятор просто берёт название исходного и меняет расширение .c на .o (указать можно, если нам захочется назвать его по-другому).

Если мы создаём объектный файл из исходника, уже обработанного препроцессором (например, такого, какой мы получили выше), то мы должны обязательно указать явно, что компилируемый файл является файлом исходного кода, обработанный препроцессором, и имеющий теги препроцессора. В противном случае он будет обрабатываться, как обычный файл C++, без учёта тегов препроцессора, а значит связь с объявленными функциями не будет устанавливаться. Для явного указания на язык и формат обрабатываемого файла служит опция -x. Файл C++, обработанный препроцессором обозначается cpp-output.

gcc -x cpp-output -c kalkul.cpp

Наконец, последний этап – компоновка. Получаем из объектного файла исполняемый.

gcc kalkul.o -o kalkul

Можно его запускать.

./kalkul

Вы спросите: «Зачем вся эта возня с промежуточными этапами? Не лучше ли просто один раз скомандовать gcc kalkul.c -o kalkul?»

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

[ опубликовано 06/09/2006 ]

Дмитрий Пантелеичев (dimanix2006 at rambler dot ru) - Знакомство с компилятором GCC

Материал взят из http://www.linuxcenter.ru/lib/books/linuxdev/linuxdev1.phtml?style=print

 

Антипаттерны


Материал из Википедии — свободной энциклопедии

  

Анти-паттерны (anti-patterns), также известные как ловушки
(pitfalls) — это классы наиболее часто внедряемых плохих решений
проблем. Они изучаются, как категория, в случае когда их хотят избежать
в будущем, и некоторые отдельные случаи их могут быть распознаны при
изучении неработающих систем.


Термин происходит из информатики, из книги «Банды четырёх» Шаблоны проектирования, которая заложила примеры практики хорошего программирования. Авторы назвали эти хорошие методы «шаблонами проектирования», и противоположными им являются «анти-паттерны». Частью хорошей практики программирования является избежание анти-паттернов.



Концепция также прекрасно подходит к машиностроению. Несмотря на то, что термин нечасто используется вне программной инженерии, концепция является универсальной.




 

Некоторые различаемые анти-паттерны в программировании



Анти-паттерны в управлении разработкой ПО


  • Дым и зеркала
    (Smoke and mirrors): Демонстрация того, как будут выглядеть
    ненаписанные функции (название происходит от двух излюбленных способов,
    которыми фокусники скрывают свои секреты).
  • Раздувание ПО (Software bloat): Разрешение последующим версиям системы требовать всё больше и больше ресурсов.
  • Функции для галочки:
    Превращение программы в конгломерат плохо реализованных и не связанных
    между собой функций (как правило, для того, чтобы заявить в рекламе, что функция есть).



Анти-паттерны в разработке ПО




Анти-паттерны в объектно-ориентированном программировании



  • Базовый класс-утилита (BaseBean): Наследование функциональности из класса-утилиты вместо делегирования к нему
  • Вызов предка
    (CallSuper): Для реализации прикладной функциональности методу
    класса-потомка требуется в обязательном порядке вызывать те же методы
    класса-предка.
  • Ошибка пустого подкласса (Empty subclass failure): Создание класса (Perl),
    который не проходит «проверку пустоты подкласса» («Empty Subclass
    Test») из-за различного поведения по сравнению с классом, который
    наследуется от него без изменений
  • Божественный объект (God object): Концентрация слишком большого количества функций в одиночной части дизайна (классе)
  • Объектная клоака (Object cesspool): Переиспользование объектов, чьё состояние не удовлетворяет (возможно неявному) контракту переиспользования.
  • Полтергейст (компьютер) (Poltergeist): Объекты, чьё единственное предназначение — передавать информацию другим объектам
  • Проблема йо-йо (Yo-yo problem): Структура (например: наследования) которая тяжело понятна вследствие избыточной фрагментации
  • Синглетонизм (Singletonitis): Избыточное использование паттерна синглетон



Анти-паттерны в программировании


  • Ненужная сложность (Accidental complexity): Внесение ненужной сложности в решение
  • Действие на расстоянии (Action at a distance): Неожиданное взаимодействие между широко разделёнными частями системы
  • Накопить и запустить (Accumulate and fire): Установка параметров подпрограмм в наборе глобальных переменных
  • Слепая вера (Blind faith): Недостаточная проверка (a) корректности исправления ошибки или (b) результата работы подпрограммы
  • Лодочный якорь (Boat anchor): Сохранение более не используемой части системы
  • Активное ожидание (Busy spin): Потребление ресурсов ЦПУ

    (процессорного времени) во время ожидания события, обычно при помощи
    постоянно повторяемой проверки, вместо того, чтобы использовать систему
    сообщений
  • Кэширование ошибки (Caching failure): Забывать сбросить флаг ошибки после её обработки
  • Проверка типа вместо интерфейса
    (Checking type instead of membership, Checking type instead of
    interface): Проверка того, что объект имеет специфический тип в то
    время, когда требуется только определённый интерфейс
  • Инерция кода (Code momentum): Сверхограничение части системы путём постоянного подразумевания её поведения в других частях системы
  • Кодирование путём исключения (Coding by exception): Добавление нового кода для поддержки каждого специального распознанного случая
  • Таинственный код (Cryptic code): Использование аббревиатур вместо мнемоничных имён
  • Жёсткое кодирование (Hard code): Внедрение предположений об окружении системы в слишком большом количестве точек её реализации
  • Мягкое кодирование

    (Soft code): Патологическая боязнь жёсткого кодирования, приводящая к
    тому, что настраивается всё что угодно, при этом конфигурирование
    системы само по себе превращается в программирование.
  • Поток лавы
    (Lava flow): Сохранение нежелательного (излишнего или
    низкокачественного) кода по причине того, что его удаление слишком
    дорого или будет иметь непредсказуемые последствия
  • Магические числа (Magic numbers): Включение чисел в алгоритмы без объяснений
  • Процедурный код (Procedural code): Когда другая парадигма является более подходящей
  • Спагетти-код (Spaghetti code): Системы, чья структура редко понятна, особенно потому что структура кода используется неправильно
  • Мыльный пузырь (Soap bubble): Класс, инициализированый мусором, максимально долго притворяется, что содержит какие-то данные.



Методологические анти-паттерны





Анти-паттерны управления конфигурацией


  • Ад зависимостей (Dependency hell): Проблемы с версиями требующихся продуктов, особенно в системах UNIX/GNU/Linux
  • DLL-ад (DLL hell): Проблемы с версиями, доступностью и увеличением количества DLL, особенно в Microsoft Windows.



Некоторые организационные анти-паттерны


  • Аналитический паралич (Analysis paralysis): Выделение непропорционально больших усилий в фазе анализа проекта
  • Дойная корова (Cash cow): Закрытый продукт, приносящий выгоду, часто ведёт к самоуспокоенности относительно новых продуктов
  • Продолжительное устаревание (Continuous obsolescence): Выделение непропорционально больших усилий портированию системы в новые окружения
  • Сваливание расходов (Cost migration): Перенос расходов на проект к уязвимому отделу или бизнес-партнёру
  • Ползущий улучшизм (Creeping featurism): Добавление новых улучшений в ущерб качеству системы
  • Разработка комитетом (Design by committee): Результат того, что имеется много содействующих разработке, но не имеется единого видения
  • Эскалация обязательств (Escalation of commitment): Продолжение реализации решения в том случае, когда неправильность его доказана.
  • Я тебе это говорил (I told you so): Когда игнорируется предупреждение эксперта, являющееся оправданным
  • Управление числами

    (Management by numbers): Уделение избыточного внимания численным
    критериям управления, когда они неважны или стоимость их получения
    слишком высока
  • Драконовские меры (Management by perkele): Военный стиль управления без толерантности к диссидентству
  • Управление грибами (Mushroom management): Удержание работников в неинформированном и занятом состоянии
  • Расползание рамок (Scope creep): Дозволение рамкам проекта расти без должного контроля
  • Замкнутость на продавце (Vendor lock-in): Изготовление системы, избыточно зависящей от внешнего поставляемого компонента
  • Тёплое тело (Warm body): Человек, чей вклад в проект под сомнением, особенно если рассмотрен в панике
  • Единственный знающий человек

    (Single head of knowledge): ЕЗЧ (SHOK) применим в том случае, когда
    единственная личность во всей организации контролирует жизненно-важную
    область ноу-хау или информации о внутренностях системы.
  • Рыцарь на белом коне
    (Knight in shining armor): РНБК (KISA) происходит тогда, когда
    личность, которая не совершает ошибок, появляется на сцене и пытается
    починить всё, без сообщений о том, какие изменения он/она
    сделал/сделает и почему.


Некоторые социальные анти-паттерны


Статус некоторых из них может быть спорным.


  • Цензура (Censorship): Подавление дискуссии для предотвращения политического, социального и научного прогресса
  • Концентрация власти (Political corruption, Concentrated power): Индивидуальное злоупотребление властью, даже с изначально хорошими помыслами
  • Демократия

    (Democracy): Большая группа индивидов не может принимать
    аргументированные решения, а руководствуется лишь поверхностной
    информацией.
  • Диктатура (Dictatorship): Ни один индивид не имеет всех умений необходимых для управления; также власть развращает
  • Дискриминация (Discrimination): Концентрация на неуместных особенностях усиливает экономическую неэффективность и социальную напряжённость
  • Догма (Dogmatic religion): Догма подавляет индивидуальное мышление и тормозит прогресс
  • Нетерпимость
    (Intolerance): Настаивание на изменении нежелательных-но-безопасных
    особенностей других людей влечёт усиление напряжённости и также
    является бесконечной задачей
  • Монополия (Monopoly): Без соперничества большинство эффектов свободного рынка не работают, и частная компания не имеет стимула действовать честно
  • Система голосования на основе большинства

    (Plurality voting system): Политика при голосовании на основе
    большинства вырождается в две полярно-противоположные партии,
    результатом чего является подавление других политических воззрений
  • Соревнование в популярности
    (Popularity contest): Популярность становится самодостаточной величиной
    и не сопоставима ни с каким другими параметрами или достоинствами
  • Сегрегация (Racial segregation): Разделение по равноправию весьма редко, если вообще существует; ведёт к напряжённости
  • Однопартийная система (Single-party system): Без избирательного соревнования партия не имеет побуждения управлять честно
  • Тоталитаризм
    (Totalitarianism): Подавление индивидуальности ведёт к напряжённости,
    вдобавок одобренный способ жизни никогда ещё не был годен для всех
  • Преступление без жертв
    (Victimless crime): Подавление безопасного поведения создаёт
    субкультуру людей, постоянно-живущих-по-другим-законам, для которых эта
    правовая система является врагом
  • Охота на ведьм

    (Witch hunt): Легко отыскать козла отпущения, но если проблема никогда
    не решается в действительности, результатом будет являться поиск всё
    новых и новых козлов отпущения
  • Нулевой Год (Year Zero): Социальное изменение является долгим процессом, ускорение его влечёт катастрофу


Шуточные анти-паттерны


  • Паблик Морозов:
    Класс-потомок, созданный в соответствии с этим антипаттерном, выдает по
    запросу все данные класса-предка, независимо от степени их сокрытия.
    Название данного анти-паттерна — это каламбур, основанный на созвучии ключевого слова public
    (паблик), часто означающего открытый доступ к методам и полям класса в
    объектно-ориентированных языках программирования, и имени пионера-героя

    Павлика Морозова, известного тем, что он выдал своего отца-кулака.


Смотрите также



Обсуждение этой темы с моим знакомым программистом можно посмотреть на http://iphonesdk.livejournal.com/4153.html

 

man xcodebuild (справка по команде)


Материал взят из www.manpagez.com



NAME

     xcodebuild -- build Xcode projects

SYNOPSIS

     xcodebuild [-project projectname] [-activetarget] [-alltargets]
[-target targetname] [-parallelizeTargets]
[-activeconfiguration] [-configuration configurationname]
[-sdk < sdkfullpath > | < sdkname >] [buildaction ...]
[setting=value ...] [-default=value ...]
xcodebuild -version [-sdk [< sdkfullpath > | < sdkname > [< single item >]]]
xcodebuild -find < binary > [-sdk < sdkfullpath > | < sdkname >]
xcodebuild -showsdks
xcodebuild -list
xcodebuild -help

DESCRIPTION
     xcodebuild builds a target contained in an Xcode project.

Usage
Run xcodebuild from the directory containing your project (i.e. the
directory containing the projectname.xcodeproj package). If you have
multiple projects in the this directory you will need to use -project to
indicate which project should be built.

By default, xcodebuild builds the first target listed in your project,
with the default build configuration. The order of the targets is a prop-
erty of the project and is the same for all users of the project. The
active target and active build configuration properties are set for each
user of the project and can vary from user to user.

Options
-project projectname
Build the project specified by projectname. Required if there are
multiple project files in the same directory.

-activetarget
Builds the user's active target.

-alltargets
Build all the targets in the project.

-target targetname
Build the target specified by targetname.

-nodependencies
Only perform the action on the specified target(s), not on any tar-
gets upon which they depend. This option only applies to the
'clean' action.

-parallelizeTargets
Build independent targets in parallel when possible. With distrib-
uted builds or multiprocessor machines, this can cause projects
with many simple targets to build substantially faster. This
option only applies to targets with target dependencies.

-activeconfiguration
Use the user's active build configuration when building the target.

-configuration configurationname
Use the build configuration specified by configurationname when
building the target.

-sdk < sdkfullpath > | < sdkname >
Build an Xcode project against the specified SDK, using build tools
appropriate for that SDK. The argument may be an absolute path to
an SDK, or the canonical name of an SDK.

-showsdks
Lists all available SDKs, including their canonical names suitable
for use with -sdk.

buildaction ...
Specify a build action (or actions) to perform on the target.
Available build actions are:

build Build the target in the build root (SYMROOT). This is
the default build action.

installsrc Copy the source of the project to the source root
(SRCROOT).

install Build the target and install it into the target's
installation directory in the distribution root
(DSTROOT).

clean Remove build products and intermediate files from the
build root (SYMROOT).

setting=value
Set the build setting setting to value.

-find binary -sdk < sdkfullpath > | < sdkname >
Print the absolute path to binary in the context of sdk. If the
-sdk argument is not provided, find uses the value of the build
setting SDKROOT, if set. Returns EINVAL if a valid SDK could not be
determined. The search order is the usr/bin directory in the SDK,
the bin directory in the SDK, then each of the paths specified by
the PATH environment variable. Returns ENOENT if the requested
binary could not be located in any of the searched directories.

NOTE: 'xcrun -find' is preferred because it caches the resulting
find; xcrun uses xcodebuild to populate its cache.

-version
Display version information. When used in conjunction with -sdk,
the version of the specified SDK is displayed, or all SDKs if -sdk
is given no value. Additionally, a single line of the reported
version information may be returned if specified.

-default=value
Set the user default default to value.

-list
Lists the targets in the project. Does not initiate a build.

-nodistribute
Disable distributed building. Overrides the distributed build set-
ting stored in the user defaults by the Xcode preferences panel.

-bonjourbuildhosts
Enable distributed building and search for build machines using
Bonjour. Build machines are added dynamically during the build as
they are discovered. May be used alone or in conjunction with
-buildhosts or -buildhostsfile.

-nobonjourbuildhosts
Do not search for build machines using Bonjour. Overrides the Bon-
jour distributed build setting stored in the user defaults by the
Xcode preferences panel.

-buildhosts hostlist
Enable distributed building and set the list of build machines to
the space separated list given in hostlist.

-buildhostsfile hostsfile
Enable distributed building and set the list of build machines to
the contents of hostsfile. hostsfile is a text file containing
build machine names, one per line.

-help
Displays usage information for xcodebuild.


EXAMPLES

     xcodebuild clean install

Cleans the build directory; then builds and installs the first
target in the project.

xcodebuild -target MyTarget OBJROOT=/Build/MyProj/Obj.root
SYMROOT=/Build/MyProj/Sym.root

Builds the target MyTarget putting object (intermediate) files in
one directory and the products of the build in another directory.

xcodebuild -sdk macosx10.4

Builds an Xcode project against the Mac OS X 10.4 SDK. The
canonical names of all available SDKs can be viewed using the
-showsdks option.

 
Теги: xcodebuild|man
 
 

Как сделать скрипт для компиляции и линковки сразу нескольких Xcode-проектов


Сегодня меня достало заниматься рутинным действием на работе - нередко после изменения/добавления хотя бы одной строчки кода приходится пересобирать добрый десяток статических либ, которые зависят от этого исходника. Этот процесс можно автоматизировать.

В Мac OS в командной строке (в терминале) всё делается примерно также, как и в любой Unix-подобной системе.

Чтобы оставаться в терминале, можно даже и не открывать текстовый отдельный редактор, потому что есть встроенные редактор vi (или vim, насколько я знаю, этот редактор очень любят старые Linux-хакеры). Справку по этому редактору можно найти во многих статьях и учебниках (посвящённых Unix/Linux).

В самом верху вашего скрипта (текстового файла, содержащего все необходимые команды для выполнения) введите:

#!/bin/bash

Для того, чтобы добавить в скрипт команду для сборки (компиляции и линковки) Xcode-проекта, добавьте строку (вместо myProject.xcodeproj нужно указать правильный путь к файлу проекта):

xcodebuild -project myProject.xcodeproj -target targetname

(насчёт аргумента, который нужно ввести вместо targetname можно выяснять набрав команду
man xcodebuild

Можно заранее сделать все настройки, открыв проект в среде разработки Xcode (и поставив все необходимые опции, используя графический интерфейс). А потом уже написать в скрипте:

xcodebuild -project myProject.xcodeproj -activetarget

При выполнении этой команды всё будет компилироваться и линковаться точно также, как если бы вы снова открыли ваш проект в среде разработки и нажали на кнопочку "Build".
 

После того, как напишите и сохраните ваш скрипт (из команд для сборки нескольких проектов), обязательно позвольте ему стать исполняемым файлом, выполнив в терминале команду (при условии, что вместо scriptFileName указан правильный путь к файлу):

chmod +x scriptFileName

Если после компиляции+линковки (т.е. после сборки бинарника) вы видите, что дата создания бинарного файла стоит старая, то это лишь из-за того, что в исходниках или настройках проекта ничего не изменялось со времени прошлой сборки бинарника.

С большим трудом нашёл информацию куда нужно вставлять слова Debug/Release, а также как выбирать между компиляцией для девайса и симулятора.

Итак, вот пример (если что задавайте здесь вопросы):

xcodebuild -project ./Desktop/MyProjectFolder/MyProject.xcodeproj -activetarget -configuration Debug -sdk iphonesimulator3.1.3

-activetarget подразумевает что имя и назначение останутся такими же, как вы выставили в среде разработки. Иначе изучайте в Гугле, как можно использовать -target вместо -activetarget.

Вместо -configuration Debug -sdk iphonesimulator3.1.3 для релизной сборки под девайс замените:
-configuration Release -sdk iphoneos3.1.3

Ну вот собственно и всё.

 

Какой аналог у SetEvent (Win32) в pthread?


Материал взят из http://electronix.ru:1288/forum/lofiversion/index.php/t47683.html

Andrey Sudnov
May 13 2008, 11:36
Проблема в том, что в библиотеке PThread нет работы с файловыми дескрипторами. Соответственно, для того чтобы одновременно ожидать завершения какой-либо файловой (или сокетовой) операции или поступления управляющего сигнала от другого потока (например, об отмене операции), приходится использовать неименнованные каналы (pipe и write, вместо SetEvent) и функцию poll (предпочитаю ее, а не select). Перерыл кучу книг, в том числе POSIX стандарт, ничего лучше не придумал. Насколько такое решение накладно по ресурсам? Как организовать такое взаимодействие потоков другим способом?
KRS
May 14 2008, 11:38
в POSIX есть mutex и Condition Variables
я когда игрался с POSIX под сигвин делал примерно так:

typedef struct {
pthread_mutex_t lock;
pthread_cond_t event;
bool flag;
}event_t;

static inline void event_init(event_t* event)
{
pthread_mutex_init(&event- >lock,0);
pthread_cond_init(&event- >event,0);
event- >flag=false;
}

static inline void event_set(event_t* event)
{
pthread_mutex_lock(&event- >lock);
if (!event- >flag) {
event- >flag=true;
pthread_cond_signal(&event- >event);
}
pthread_mutex_unlock(&event- >lock);
}

static inline bool event_wait(event_t* event, unsigned s_timeout)
{
bool r;
pthread_mutex_lock(&event- >lock);
if(!event- >flag) {
if (s_timeout) {
timespec_t timer;
clock_gettime(CLOCK_REALTIME,&timer);
timer.tv_sec+=s_timeout;
pthread_cond_timedwait(&event- >event,&event- >lock,&timer);
}else {
do {
pthread_cond_wait(&event- >event,&event- >lock);
}while(!event- >flag);
}
}
r=event- >flag;
event- >flag=false;
pthread_mutex_unlock(&event- >lock);
return r;
}
RCray
May 15 2008, 12:05
да. это даже лучше, чем poll, который не для всех устройств реализован. к тому же в вашем коде подчерпнул кое-что для себя, спасибо.
RCray
May 15 2008, 13:23
только у меня так:


void* child_func(void* arg)
{
struct args_t* args = (args*)arg;

args- >size = read(args- >fd, args- >packet, args- >supposed_size);
args- >event.flag = 1;
pthread_cond_signal(&args- >event.event);

return 0;
}

int parent(struct args_t *args)
{
pthread_t child;
struct timespec tm;

if ( pthread_create(&child, NULL, child_func, args) != 0 )
return ERR_CREATE;

// задание таймаута
...

while(!args- >event.flag)
{
res = pthread_cond_timedwait(&args- >event.event, &args- >event.lock, &tm);
if (res == ETIMEDOUT)
return ERR_TIMEOUT;
}

args- >event.flag = 0;
return args- >errors;
}

KRS
May 15 2008, 15:31
Без mutex есть потенциальные проблемы:
если между проверкой и очисткой возникнет еще одно событие вы его потеряете потому что обнулите args- >event.flag = 0;

(2b|!2b?.. @ May 15 2008, 14:08) [snapback]411551[/snapback]


while(!args- >event.flag)
{
res = pthread_cond_timedwait(&args- >event.event, &args- >event.lock, &tm);
if (res == ETIMEDOUT)
return ERR_TIMEOUT;
}

args- >event.flag = 0;
return args- >errors;
}



RCray
May 15 2008, 15:59
(KRS @ May 15 2008, 16:16) [snapback]411655[/snapback]

Без mutex есть потенциальные проблемы:
если между проверкой и очисткой возникнет еще одно событие вы его потеряете потому что обнулите args- >event.flag = 0;


да, опять вы правы.
к тому же не лишним будет это

res = pthread_cond_timedwait(&args- >event.event, &args- >event.lock, &tm);
if (res == ETIMEDOUT)
{
pthread_cancel(созданный ранее поток, от которого ожидается сигнал);
return ERR_TIMEOUT;
}

Andrey Sudnov
May 18 2008, 07:14
Не нахожу ответа на свой вопрос... Уточняю условие.
Можно использовать poll, можно select, разницы нет, дело вкуса. Проблема в том, что БЕЗ этих функций невозможно отследить окончание операции с файлом (read, write, recv, send, conect, etc...).
Ситуация следующая. Есть два потока. Один - интерфейс, и там есть кнопка Exit. Другой - работа с сокетами. Работа с сокетами должна быть немедленно прекращена, как только нажали кнопку Exit. Для этого необходимо ждать одновременно и файловый дескриптор (poll/select) и event от pthread (если мы работаем через них). Это невозможно - нет такой функции. В Windows есть такой тип: HANDLE. Он общий и для событий (SetEvent) и для дескрипторов ввода/вывода. Соответственно, оба можно одновременно передать в функцию WaitForMultipleObjects.
Вижу два варианта. Первый: вызывать poll/select с установленным таймаутом в несколько миллисекунд, затем проверять событие и так по кругу. С кнопкой это конечно прокатит, но в случае жесткого реального времени задержка на обработку события будет составлять именно этот таймаут. К тому же постоянное верчение в юзеровском коде не делает чести с точки зрения использования ресурсов и производительности.
Второй вариант: отказаться от синхронизирующих функций pthread нафиг. Использовать pipe. Здесь встает вопрос, насколько эффективно реализованы эти каналы в коде ОС/libc. И не перекрывает ли потенциальная кривая реализация преимуществ над первым вариантом?
Варианты еще?
vshemm
May 18 2008, 17:31
(Andrey Sudnov @ May 18 2008, 07:59) [snapback]412873[/snapback]

Второй вариант: отказаться от синхронизирующих функций pthread нафиг. Использовать pipe. Здесь встает вопрос, насколько эффективно реализованы эти каналы в коде ОС/libc. И не перекрывает ли потенциальная кривая реализация преимуществ над первым вариантом?

А ОС, собственно, какая?
Впрочем, если не нравятся пайпы, можно использовать сокеты smile.gif Для них есть высокоэффективная реализация оповещения об изменении состояния, правда, механизмы в разных ОС разные. Гляньте сюда - http://monkey.org/~provos/libevent/
Так или иначе, задержки будут намного меньше таймаута в неск. миллисекунд при небольшом количестве сокетов.

Варианты еще?

Сигналы?

А вот что пишет Steven Grimm (http://monkeymail.org/archives/libevent-users/2007-January/000450.html):

no UNIX-ish system I'm aware of has an equivalent to the Windows
WaitForMultipleObjects API that allows you to wake up on semaphores /
condition variables and on input from the network. Without that, any
solution is going to end up using pipes (or maybe signals, which have
their own set of issues in a multithreaded context) to wake up the
libevent threads.

однако, про локальные сокеты он почему-то не упоминает.

И еще smile.gif Вы зря,имхо, предпочитаете poll select'у, т.к. poll при каждом вызове гоняет структу в ядро = > большой оверхед. С другой стороны селект имеет ограничени на кол-во дескрипторов. Во всяком случае в linux это так, поэтому и появился epoll().

 

Pthread Condition Variables и Windows Events (Креатив)


Материал взят из http://mejedi.livejournal.com/27180.html

Две такие похожие истории...

* Condition Variables
Жили-были процессы и была у них на всех одна открывашка. Когда процесс хочет выпить пива, он хватает открывашку. Если после этого процесс обнаруживает, что открывать ему нечего, он скрепя сердце возвращает открывашку и встает в одну из очередей.

Иногда приходит добрый дядька с пивом. Если в очереди никого нет, он тут же уходит.

1. pthread_cond_signal()
Приходит добрый дядька, приносит первому процессу в очереди бутылку пива и уходит. Процесс бежит хватать открывашку.

2. pthread_cond_broadcast()
Приходит добрый дядька, приносит всем процессам в очереди по пиву, и уходит. Процессы наперегонки бегут хватать открывашку.

Бывает так, что процессу не нравится полученное пиво. Тогда он снова встает в очередь.

* Events
Жили были процессы и была у каждого своя открывашка. Когда процессы хотят выпить пива, они выстраиваются в очереди. Очередь обслуживают двое дядек с очень разными характерами – Manual Reset Дядько и Auto Reset Дядько.

M.R. Дядько очень терпеливый. Он выдает всем стояльцем в очереди по пиву, и ждет чтобы кто-нибудь пришел еще. Всем новоприбывшим Дядько тоже дает пиво. Если управляющий не отзовет дядьку, он так и будет бесконечно всем давать пиво.

A.R. Дядько тоже терпеливый. Если он пришел – а в очереди никого, он подождет. С собой у Дядько только одна бутылка, поэтому он уйдет как только отдаст её первому процессу в очереди.

1. SetEvent()
Позвать дядьку.

2. ResetEvent()
Прогнать дядьку.

3. PulseEvent()
Управляющей звонит дядьке и говорит чтобы он принес пива. Потом перзванивает, и говорит что передумал. Потом звонит снова и говорит что пиво всё-таки надо нести. И так много раз. Дядька может сойти с ума и всех поубивать.


Между ними нет ничего общего. Auto Reset Event и pthread_cond_signal() ничем не похожи. Manual Reset Event не имеет никакого отношения к бродкастам. Отличия в самой модели. Pthread Condition Variables мгновенны, а Windows Events инерционны.

Когда сигналится condition variable, создается мгновенный и актуальный список ожидающих на c/v процессов. Далее пробуждаются или все процессы или только первый. Из-за этой мгновенности c/v всегда используется только вместе с мьютексом, чтобы не прозевать событие, которое сигналится с помощью c/v.

Семантика такова – pthread_cond_wait() принимает указатель на c/v и залоченный мьютекс. Затем атомарно разлочивается мьютекс и процесс ждет пока c/v не будет просигналена. Наконец мьютекс захватывается снова, и pthread_cond_wait() завершается. Предполагается, что если c/v просигналена пока процесс держит мьютекс, это можно безопасно проигнорировать. Обычно это на самом деле так, потому что используется мьютекс, который защищает структуру данных, изменение состояния которой сигналится с помощью c/v. Если мы взяли мьютекс, то можем спокойно проверить данные на предмет соответствия интересующему нас состоянию. Классический пример – защищенная мьютексом очередь сообщений и c/v, которая сигналится при каждом помещении собщения в очередь.

Напротив, в ОС Windows невозможно сформировать актуальный список процессов, ожидающих на определенном объекте. В процесс может быть доставлена kernel-mode APC, после чего процесс временно покинет состояние ожидания. Второй источник инерционности – это семантика функции WaitForMultipleObjects(bWaitAll=TRUE). Процесс не покинет состояние ожидания до тех пор, пока все объекты не перейдут в signaled state. Концепция этого самого signaled state напрямую диктует, что примитивы синхронизации инерционны. Объект может потерять signaled state если разблокируется ожидающий на нем процесс, просто так потерять signaled state нельзя.

Бесполезно передергивать Auto Reset Event чтобы достичь эффекта бродкаста. Manual Reset Event также бесполезно передергивать. Попытка сделать это вручную – SetEvent(); ResetEvent(); – также не даст результатов. Нет гарантий, что в промежутке между установкой и сбросом события кто-то успеет заметить изменение состояния события и разблокируется.

Это конечно не значит, что conditional variable нельзя сделать в Windows. Очевидно, придется собирать conditional variable из нескольких независимых примитивов синхронизации. Её не получится использовать в WaitForMultipleObjects() совместно с другими объектами синхронизации.

 

Шпаргалка по TinyXML


Материал взят отсюда

Минимальный набор
TinyXML содержит в себе:


  • tinyxml.h
  • tinyxml.cpp
  • tinystr.cpp
  • tinyxmlerror.cpp
  • tinyxmlparser.cpp

Алгоритм работы
проще некуда, попробуем распарсить следующий
кусочек XML документа:


< Parent >



< Child param="param1"
value="value1" / >


< Child param="param2"
value="value2" / >


< Child param="param3"

value="value3" / >


< /Parent >
 
 


Текст функции:


//Создаем объект
документа XML и передаем ему имя файла
из которого


//мы будем читать


TiXmlDocument doc(fileName);
 
 


//Читаем файл
и проверяем - прочитался ли.
В случае невозможности



//чтения или распарсивания
функция вернет ошибку
 

if(!doc.LoadFile()) 

return; 
 


//Класс TiXmlElement
- это основной кирпичик, на которые разбит


//документ XML.
Функция FirstChildElement возвращает первый элемент
в списке


//имя
которого "Parent".



TiXmlElement *element = doc.FirstChildElement("Parent");
 
 


//Берем
первый елемент под
именем "Child"
 

element = element- >FirstChildElement("Child");


//Перебираем все
элементы с именем "Child"
 

while(element != NULL) 


{


//Переменные для
извлечения значений из документа
 

std::string param; 

std::string value;


//Функция QueryValueAttribute
"достает" из документа значения
атрибутов


//Следует сказать,
что функция перегружена для сех основных
типов данных


//включая строки
из стандартной библиотеки



//Если функция
вернула код TIXML_SUCCESS, то параметр считался
 

if(element- >QueryValueAttribute("param", &param) ==
TIXML_SUCCESS && 

element- >QueryValueAttribute("value", &value) == TIXML_SUCCESS) 

//Здесь мы производим действия над извлеченными
данными


...  



//Выбираем следующий
элемент из списка. Если элемент не существует


//то на следующей
итерации мы выйдем из цикла


element = element- >NextSiblingElement("action"); 

 



Таким образом,
мы легко и непринужденно можем считать,
к примеру, настройки своей программы
или какие-то типизированные данные. В
XML файле вполне может храниться небольшая
база данных или файл сохранения для игрового
момента ;)


 


Библиотека TinyXML
предоставляет программисту очень удобный
способ работы с XML. Для примера возьмем
такой фрагмент XML-файла:  

  

< level name="Demo Level 1" > 

< entity class="Car" pos="300,250,300" > 


< body mass="20" / > 

< /entity > 

< entity class="Robot" pos="100,250,100" > 

< /level >  

  


Теперь фрагмент кода на С++, который иллюстрирует
работу с TinyXML (предварительно подключив
заголовочный файл библиотеки директивой
"#include" и внеся строку "tinyxml.lib"
в конфигурацию линковщика).  

  

//Открываем XML-файл: 

TiXmlDocument *xml_file = new TiXmlDocument("путь_к_файлу"); 


if(!xml_mtl_file- >LoadFile()) 

    return false;  

  

Следует учесть, что файл должен быть валидным,
т. е. не содержать ошибок. Например все
теги должны быть правильным образом закрыты
(< body / > или < body >< /body >) и так далее. 

После открытия файла мы находимся в его
корне, поэтому элемент < level > будет являться
первым дочерним элементом всего файла.
Доступ к нему мы можем получить так:  


  

TiXmlElement *xml_level = 0; 

xml_level = xml_file- >FirstChildElement("level");  

  

Функция FirstChildElement(имя_элемента) возвращает
указатель на первый дочерний элемент
объекта xml_file. Элемент < level > имеет дочерний

элемент < entity >, поэтому доступ к нему
мы получим уже через xml_level:  

  

TiXmlElement *xml_entity = 0; 

xml_entity = xml_level- >FirstChildElement("entity");  

  

Поскольку элементов < entity > у нас несколько,
мы можем циклически пройтись по ним используя
функцию NextSiblingElement(имя_элемента), которая
возвращает указатель на соседний с текущим

элемент XML-файла:  

  

while(xml_entity != NULL) 



    //выполняем различные действия 

    //...  

  

    xml_entity = xml_entity- >NextSiblingElement("entity"); 


}  

  

Теперь, когда мы знаем как пройтись по
всем элементам XML-файла остается только
один важный и нужный момент - атрибуты
элемента. Получить их значение (типа const
char *) можно так:  

  

//значение атрибута class элемента < entity > 

xml_entity- >Attribute("class"); 

//значение атрибута name элемента < level > 


xml_level- >Attribute("name");  

  

Скачать библиотеку и документацию к ней
можно на сайте
http://www.grinninglizard.com/tinyxml/
size="3" face="Times New Roman" >.


 

Мои любимые книги по программированию


Эти книги лежат у меня на книжных полках (часть уже изучена, остальные ждут своего часа). Эти книги не устаревают с годами (в отличие от книг, описывающие конкретные версии сред программирования).



Полные справочники и учебники Герберта Шилдта. Купил себе почти все эти книги (автор обладает талантом просто излагать сложные вещи):


C# 3.0. Полное руководство.


C# 2.0. Полное руководство


Полный справочник по C



Полный справочник по C++ (проштудировал)


C++: базовый курс (изучил от корки до корки)


Полный справочник по Java.


Язык программирования C (Брайан Керниган, Деннис Ритчи)


Просто классическая книга. С этой книги я начал изучение мира Си/Си++, поэтому питаю к ней особые чувства (это как первая любовь). Книга маленькая как и сам язык Си без плюсов, и поэтому в ней нет ничего лишнего.



Объектно-ориентированное программирование на C++ (Р. Лафоре)


Из всех прочитанных учебников по Си++ эта книга мне понравилась больше всего.


Джоэл о программировании (Джоэл Спольски)


Прочитал с огромным удовольствием (в книге много эмоций, и это делает прочтение не только полезным но и занятным). Думаю заказать другие его книги, но есть опасение, что эти книги будут повторять содержание уже прочитанной книги...


Учебники В. Фаронова по C#, Pascal и Delphi (этот автор мне показался достаточно понятным и логично всё излагает). Вот ссылки на его учебники (но я не уверен, что знание Delphi сейчас хорошо востребовано...):


Турбо Паскаль


Delphi. Программирование на языке высокого уровня



Создание приложений с помощью С#. Руководство программиста (+ CD-ROM)


Объектно-ориентированный анализ и проектирование с примерами приложений (Гради Буч)


Прочитал большую часть прежнего издания в виде html-учебника, поэтому не раздумывая купил эту книгу у знакомого программиста (достаточно дорого).


Объектно-ориентированное конструирование программных систем (Бертран Мейер)


Прочитал в онлайне несколько страниц и меня впечатлило. Должен вас предупредить, что в книге используются примеры на языке Eiffel - ни разу не видел в объявлениях, чтобы программисты на таком языке были востребованы. Тем не менее, общие концепции программирования в этой книге я планирую прочитать (перевод и стиль автора показался вполне приличным). В тонкости языка Eiffel я скорее всего вникать не буду (просто буду пролистывать эти страницы).


БЫСТРАЯ РАЗРАБОТКА ПРОГРАММ (Роберт К. Мартин, Джеймс В. Ньюкирк, Роберт С. Косс)



Я прочитал более половины этой книги, и она мне понравилась (многие рекомендуют прочесть её перед Паттернами проектирования Банды Четырёх)).

Мифический человеко - месяц или Как создаются программные системы (Фредерик Брукс)


Легендарная книга. Особенно мне нравится в этой книге мысль о том, что программист необычайно радуется, когда программа начинает работать (поэтому рекомендуется наращивать программу маленькими шагами, добиваясь каждый раз, чтобы программа исправно работала хотя бы на уровне пустой болванки). Ещё мне нравится мысль о том, что демократия при разработке программных продуктов способна повредить концептуальной целостности проекта. Прочитал её от корки до корки.

Стандарты программирования на C++ (Герб Саттер, Андрей Александреску)


Полностью её прочитал, и буду читать ещё не один раз.

Современное проектирование на С++. Серия С++ In-Depth (Андрей Александреску)


Планирую тщательно изучить (слышал положительные отзывы об этой книге).


От каких книг я ожидал большего:





Язык C++ (Б. Страуструп)


Возможно, в следующий раз эта книга понравится мне больше, ведь я уже больше года работаю программистом на C++ (и более 3-х лет использую этот язык).


Паттерны проектирования (Банда четырёх или GoF) - без этой книги мне никуда, ведь это классика, но я очень хотел бы, чтобы каждый паттерн был разжёван в весёлом эмоциональном духе на множестве простых примеров из жизни программистов. Но тогда это была бы очень толстая книга. Никаких претензий к этому очень важному справочнику - просто я ещё недостаточно дорос до этой книги, но всё равно буду её изучать.


Книги Стива Макконела - безусловно это всемирно известный автор очень ценных книг, но после знакомства со стилем Джоэла Спольски мне стало казаться, что Макконелу не хватает эмоциональности в его книгах. Больше всего мне из книг Макконела нравится Совершенный код.

 

Из блога Сергея Меднова: Знает ли Apple, для чего нужен iPad?


Материал взят из http://www.cnews.ru/reviews/index.shtml?2010/04/12/386222

12.04.10, Пн, 10:20, Мск
Бизнес

Сергей Меднов, руководитель блока "Информационные технологии" "Альфа-Банка", делится своими впечатлениями о последних ИТ-новинках и тенденциях развития современного мира ИТ.

Знает ли Apple, для чего нужен iPad?

Я живу в мире Apple и пользуюсь практически всеми изобретениями этой компании. Айфоны, макбуки, Time Capsules – все они находятся вокруг меня на рабочем столе, не считая других менее значимых девайсов. Я также активно пользуюсь различными интернет-сервисами Apple, начиная с iTunes и заканчивая MobileMe. Словом, налицо полная зависимость от продуктов Apple, благодаря которой я становлюсь одним из первых покупателей каждой новинки этой компании.

Поэтому когда появилась возможность купить очередную новинку iPad, я в первых рядах бросился заказывать это устройство. Как пишут некоторые аналитики, с началом продаж iPad в Штатах в Россию неофициально было ввезено несколько тысяч устройств. Но, сделав заказ, я задумался – а для чего, собственно говоря, мне нужен iPad? Все-таки я ценю продукты Apple за их функциональность и за то, что они позволяют эффективно структурировать окружающие меня потоки информации. Полезность iPad, который руководство компании позиционирует как очередной прорыв, для меня далеко не очевидна. Да, iPad существенно дешевле MacBook, по функционалу и удобству сопоставим с iPhone, но что с ним делать, не совсем понятно. Камера и микрофон в устройстве не предусмотрены – поэтому использование iPad, например, для общения через Skype не годится. Одновременно iPad лишен порта USB – т.е. внешние устройства вроде фотоаппарата или принтерак нему подключить не удастся. Также, как мне видится, iPad не очень удобен для набора текста. И наконец, что меня поразило – это несъемная батарея, которую сам Apple меняет в США приблизительно за 100 долларов. Только при этом замена батареи означает потерю всех сохраненных данных. Поэтом пока остается, как мне кажется, одно – использовать iPad в качестве коммуникатора с большим экраном для работы с Facebook или другими сайтами. Говорят, что iPad также будет оптимизирован для работы с различными "книжными" приложениями.

Итак, на первый взгляд, с точки зрения бизнес-идеи в текущий момент iPad выглядит не очень убедительно, хотя и стоит относительно дешево. Не случайно к моменту выхода нового девайса практически каждое деловое издание на западе вышло с материалами, озаглавленными наподобие "Понимает ли Apple, кому нужен iPad", "Нужен ли мне iPad", "Сможет ли Стив Джобс сделать это снова" и т.д. Не думаю, что Стив Джобс и другие создатели нового продукта не думали об этом, тем более они точно хорошо помнят провал других попыток по изготовлению успешной "таблетки" - собственный Apple Newton и Tablet PC конкурента Microsoft.

Не исключено, что Apple рассчитывает на активные продажи нового гаджета в Китае. В одном из блогов я читал, что в Китае уже продано более 3 млн iPnone, а магазин Apple в Пекине ничем не уступает своем "брату" в Нью-Йорке. Другой вариант – сделать iPad первым компьютером для тех, кто считает современные ПК слишком сложными и поэтому он может стать излюбленным устройством "домохозяек" или недавно прикоснувшихся к цивилизации диких племен.

Возможно, нужно просто оставить в сторону прагматизм и "довериться" инновационному подходу Apple, которая и выжила благодаря опережению потребительских предпочтений. iPad – это проба пера на пути создания нового типа компьютера. Нечто вроде нового Макинтоша, в свое время произведшего революцию на рынке мобильных компьютеров. Я всегда в таких случаях вспоминаю историю, которую любит повторять Стив Форбс. Если в 70-х годах вы подошли бы к среднестатистическому пользователю и предложили ему купить современный компьютер, описав его характеристики, он бы сказал, что ему вполне хватит имеющейся у него печатной машинки.

Apple каким-то магическим образом умеет комбинировать потребительские свойства устройств, прикрепляя к ним сильную эмоциональную окраску бренда, делая вещи, которые уже существовали до новых продуктов компании, по-настоящему культовыми. Взять тот же iPod – цифровые плееры существовали задолго до продукта Apple, но только Стив Джобс сумел сделать это устройство массовыми.

Но в конечном итоге все будет зависеть от того, сможет ли Apple придать новому девайсу расширенные потребительские свойства. С этой целью, как минимум, нужно разработать специальный софт для этого устройства – игры, офисные приложения и т.д. В ближайшее время iPad окажется у меня на столе, и я попробую беспристрастно оценить, смог ли Apple сделать это снова.

 
 
 

Вопросы на проверку знания языка C++


Я считаю, что программист iPhone-приложений может и должен хорошо владеть языком C++ (или стремиться к этому). Можно конечно, ограничиться только применением Objective C, но лично я советую использовать всю мощь C++.

Материал взят из http://www.rsdn.ru/forum/cpp/1870577.1.aspx

1. Что определяет класс? Чем обличается класс от объекта?
2. Можно ли объявлять массив объектов? А массив классов?
3. Разрешается ли объявлять указатель на объект? А указатель на класс?
4. Допускается ли передавать объекты в качестве параметров, и какими способами? А возвращать как результат?
5. Как называется использование объекта одного класса в качестве поля другого класса?
6. Является ли структура классом? Чем класс отличается от структуры?
7. Какие ключевые слова в С++ обозначают класс?
8. Объясните принцип инкапсуляции.
9. Что такое композиция?
10. Для чего используются ключевые слова public и private?
11. Можно ли использовать ключевые слова public и private в структуре?
12. Существуют ли ограничения на использование public и private в классе? А в структуре?
13. Обязательно ли делать поля класса приватными?
14. Что такое метод? Как вызывается метод?
15. Может ли метод быть приватный?
16. Как определить метод непосредственно внутри класса? А вне класса? Чем эти определения отличаются?
17. Можно в методах присваивать параметрам значения по умолчанию?
18. Что обозначается ключевым словом this?
19. Зачем нужны константные методы? Чем отличается определение константного метода от обычного?
20. Может ли константный метод вызываться для объектов-переменных? А обычный метод — для объектов-констант?
21. Объясните принцип полиморфизма.
22. Сколько места в памяти занимает объект класса? Как это узнать?
23. Каков размер «пустого» объекта?
24. Влияют ли методы на размер объекта?
25. Одинаков ли размер класса и аналогичной структуры?
26. Какие операции нельзя перегружать? Как вы думаете, почему?
27. Можно ли перегружать операции для встроенных типов данных?
28. Можно ли при перегрузке изменить приоритет операции?
29. Можно ли определить новую операцию?
30. Перечислите особенности перегрузки операций как методов класса. Чем отличается перегрузка внешним образом от перегрузки как метода класса?
31. Какой результат должны возвращать операции с присваиванием?
32. Как различаются перегруженная префиксная и постфиксная операции инкремента и декремента?
33. Что означает выражение *this? В каких случаях оно используется?
34. Какие операции не рекомендуется перегружать как методы класса? Почему?
35. Какие операции разрешается перегружать только как методы класса?
36. Дайте определение дружественной функции. Как объявляется дружественная функция? А как определяется?
37. Дайте определение конструктора. Каково назначение конструктора? Перечислите отличия конструктора от метода.
38. Сколько конструкторов может быть в классе? Допускается ли перегрузка конструкторов? Какие виды конструкторов создаются по умолчанию?
39. Может ли конструктор быть приватным? Какие последствия влечет за собой объявление конструктора приватным?
40. Приведите несколько случаев, когда конструктор вызывается неявно.
41. Как проинициализировать динамическую переменную?
42. Как объявить константу в классе? Можно ли объявить дробную константу?
43. Каким образом разрешается инициализировать константные поля в классе?
44. В каком порядке инициализируются поля в классе? Совпадает ли этот порядок с порядком перечисления инициализаторов в списке инициализации конструктора?
45. Какие конструкции С++ разрешается использовать в списке инициализации качестве инициализирующих выражений?
46. Какой вид конструктора фактически является конструктором преобразования типов?
47. Для чего нужны функции преобразования? Как объявить такую функцию в классе?
48. Как запретить неявное преобразование типа, выполняемое конструктором инициализации?
49. Какие проблемы могут возникнуть при определении функций преобразования?
50. Для чего служит ключевое слово explicit?
51. Влияет ли наличие целочисленных констант-полей на размер класса?
52. Разрешается ли объявлять массив в качестве поля класса. Как присвоить элементам массива начальные значения?
53. Сколько операндов имеет операция индексирования []? Какой вид результата должна возвращать эта операция?
54. Для чего нужны статические поля в классе? Как они определяются?
55. Как объявить в классе и проинициализировать статический константный массив?
56. Что такое выравнивание и от чего оно зависит? Влияет ли выравнивание на размер класса?
57. Дайте определение контейнера.
58. Какие виды встроенных контейнеров в С++ вы знаете?
59. Какие виды доступа к элементам контейнера вам известны?
60. Чем отличается прямой доступ от ассоциативного?
61. Перечислите операции, которые обычно реализуются для последовательного доступа к элементам контейнера.
62. Дайте определение итератора.
63. Можно ли реализовать последовательный доступ без итератора? В чем преимущества реализации последовательного доступа с помощью итератора?
64. Что играет роль итератора для массивов С++?
65. Что такое деструктор? Может ли деструктор иметь параметры?
66. Почему для классов-контейнеров деструктор надо писать явным образом?
67. Допускается ли перегрузка деструкторов?
68. Что такое «глубокое копирование» и когда в нем возникает необходимость?
69. Какое копирование осуществляет стандартный конструктор копирования?
70. Чем отличается копирование от присваивания?
71. Объясните, почему в операции присваивания требуется проверка присваивания самому себе?
72. Можно ли в качестве операции индексирования использовать операцию вызова функции ()? В чем ее преимущества перед операцией []?
73. Почему необходимо писать два определения операции индексирования? Чем они отличаются?
74. Дайте определение вложенного класса.
75. Можно ли класс-итератор реализовать как внешний класс? А как вложенный? В чем отличия этих методов реализации?
76. Может ли объемлющий класс иметь неограниченный доступ к элементам вложенного класса? А вложенный класс — к элементам объемлющего?
77. Ограничена ли глубина вложенности классов?
78. Можно ли определить вложенный класс внешним образом? Зачем это может понадобиться?
79. Каким образом вложенный класс может использовать методы объемлющего класса? А объемлющий — методы вложенного?
80. Что такое «запредельный» элемент, какую роль он играет в контейнерах?
81. Объясните, по каким причинам трудно написать универсальный контейнер, элементы которого могут иметь произвольный тип.
82. Назовите ключевые слова С++, которые используются для обработки исключений.
83. Исключение — это:
1) событие;
2) ситуация;
3) объект;
4) ошибка в программе;
5) прерывание;
84. Каким образом исключение генерируется?
85. Каковы функции контролируемого блока?
86. Что обозначается ключевым словом catch?
1) контролируемый блок;
2) блок обработки исключения;
3) секция-ловушка;
4) генератор исключения;
5) обработчик прерывания;
87. Какого типа может быть исключение?
88. Сколько параметров разрешается писать в заголовке секции-ловушки?
89. Какими способами разрешается передавать исключение в блок обработки?
90. Объясните, каким образом преодолеть ограничение на передачу единственного параметра в блок обработки.
91. Почему нельзя выполнять преобразования типов исключений при передаче в секцию-ловушку?
92. Напишите конструкцию, которая позволяет перехватить любое исключение.
93. Могут ли контролируемые блоки быть вложенными?
94. Зачем нужен «контролируемый блок-функция» и чем он отличается от обычного контролируемого блока?
95. Перечислите возможные способы выхода из блока обработки.
96. Каким образом исключение «передать дальше»?
97. Сколько секций-ловушек должно быть задано в контролируемом блоке?
98. Что такое «спецификация исключений»?
99. Что происходит, если функция нарушает спецификацию исключений?
100. Учитывается ли спецификация исключений при перегрузке функций?
101. Что такое «иерархия исключений»?
102. Существуют ли стандартные исключения? Назовите два-три типа стандартных исключений.
103. Поясните «взаимоотношение» исключений и деструкторов.
104. Объясните, зачем может понадобиться подмена стандартных функций завершения.
105. Какие виды нестандартных исключений вы знаете?
106. В чем отличие механизма структурной обработки исключений Windows от стандартного механизма?
107. Какие две роли выполняет наследование?
108. Какие виды наследования возможны в С++?
109. Чем отличается модификатор доступа protected от модификаторов private и public?
110. Чем открытое наследование отличается от закрытого и защищенного?
111. Какие функции не наследуются?
112. Сформулируйте правила написания конструкторов в производном классе.
113. Каков порядок вызова конструкторов? А деструкторов?
114. Можно ли в производном классе объявлять новые поля? А методы?
115. Если имя нового поля совпадает с именем унаследованного, то каким образом разрешить конфликт имен?
116. Что происходит, если имя метода-наследника совпадает с именем базового метода?
117. Сформулируйте принцип подстановки.
118. Когда выполняется понижающее приведение типов?
119. Объясните, что такое «срезка» или «расщепление».
120. Объясните, зачем нужны виртуальные функции.
121. Что такое связывание?
122. Чем «раннее» связывание отличается от «позднего»?
123. Какие два вида полиморфизма реализованы в С++?
124. Дайте определение полиморфного класса.
125. Может ли виртуальная функция быть дружественной функцией класса?
126. Наследуются ли виртуальные функции?
127. Каковы особенности вызова виртуальных функций в конструкторах и деструкторах?
128. Можно ли сделать виртуальной перегруженную операцию, например, сложение?
129. Может ли конструктор быть виртуальным? А деструктор?
130. Как виртуальные функции влияют на размер класса?
131. Как объявляется «чистая» виртуальная функция?
132. Дайте определение абстрактного класса.
133. Наследуются ли чистые виртуальные функции?
134. Можно ли объявить деструктор чисто виртуальным?
135. Чем отличается чистый виртуальный деструктор от чистой виртуальной функции?
136. Зачем требуется определение чистого виртуального деструктора?
137. Наследуется ли определение чистой виртуальной функции?
138. Приведите классификацию целей наследования.
139. Объясните разницу наследования интерфейса от наследования реализации.
140. Назовите причины, требующие разделения программ на части.
141. Дайте определение термина «единица трансляции»?
142. Чем отличается файл с исходным текстом от единицы трансляции?
143. Существуют ли в С++ конструкции, позволяющие идентифицировать отдельный модуль?
144. Какие способы сборки программы вы можете назвать?
145. Что такое «объектный модуль»? Программа, которая «собирает» объектные модули в программу, называется _____________ ?
146. В чем заключается отличие аргумента «файл» от < файл > в директиве #include?
147. Что такое ODR?
148. Объясните, что такое «страж» включения и зачем он нужен.
149. Является ли интерфейс класса его определением?
150. Сколько определений класса может быть в единице трансляции?
151. Сколько определений класса может быть в многофайловой программе?
152. Чем отличаются стандартные заголовки , и ?
153. Объясните суть идиомы Pimpl.
154. Что такое делегирование и как его можно использовать для повышения степени инкапсуляции?
155. Каким образом глобальную переменную, определенную в одной единице трансляции, сделать доступной в другой единице трансляции? А константу?
156. Можно ли использовать слово extern при объявлении функций?
157. Как локализовать объявление функции в файле?
158. Чем отличается «внешнее» связывание от «внутреннего» связывания?
159. Что такое «спецификации компоновки»?
160. Какие объекты обладают внутренним связыванием по умолчанию?
161. Какие области видимости имен вы знаете?
162. Для чего используются пространства имен?
163. Чем отличаются именованные и неименованные пространства имен?
164. Могут ли пространства имен быть вложенными?
165. Для чего применяются алиасы пространства имен?
166. Как сделать члены пространства имен доступными в нескольких (в пределе — во всех) файлах программного проекта?
167. Объясните разницу между статической и динамической инициализацией.
168. В чем состоит проблема инициализации глобальных статических переменных?
169. Какие элементы класса можно объявлять статическими?
170. Можно ли объявить в классе статическую константу? А константный статический массив?
171. А какие статические поля можно инициализировать непосредственно в классе?
172. Как определяются статические поля? В какой момент работы программы выполняется инициализация статических полей?
173. Сколько места в классе занимают статические поля ?
174. Чем отличается статический метод от обычного?
175. Какие методы класса не могут быть статическими?
176. Какие применения статических полей вы можете привести? А каким образом применяются статические методы?
177. Приведите структуру и принцип действия паттерна Singleton.
178. Для чего предназначены шаблоны?
179. Какие виды шаблонов в С++ вы знаете?
180. Объясните термин «инстанцирование шаблона».
181. В чем разница между определением и объявлением шаблона?
182. Объясните назначение ключевого слова typename.
183. Какие виды параметров разрешается задавать в шаблоне класса? А в шаблоне функции?
184. Можно ли параметрам шаблона присваивать значения по умолчанию?
185. Может ли параметром шаблона быть другой шаблон? Каковы особенности объявления параметра-шаблона?
186. Что такое специализация шаблона? Объясните разницу между полной и частичной специализацией.
187. Разрешается ли специализировать шаблон функции?
188. Может ли класс-шаблон быть вложенным в другой класс-шаблон? А в обычный класс?
189. Можно ли объявить в классе шаблонный метод? А шаблонный конструктор?
190. Можно ли перегружать функцию-шаблон?
191. Какие параметры функции-шаблона выводятся автоматически?
192. Может ли шаблон класса быть наследником обычного класса? А обычный класс от шаблона?
193. Объясните, что такое класс свойств (класс трактовок).
194. Каким образом можно использовать возможность наследования обычного класса от шаблона?
195. Может ли шаблонный конструктор быть конструктором по умолчанию?
196. Для чего применяются директивы явного инстанцирования?
197. Объясните, в чем состоят проблемы, возникающие при разделении шаблонного класса на интерфейс и реализацию?
198. Что такое «модель явного инстанцирования» и как она работает?
199. Может ли шаблонный класс иметь «друзей»?
200. Какие проблемы возникают при объявлении дружественной функции для класса-шаблона?
201. Разрешается ли определять в классе-шаблоне статические поля? А статические методы?
202. Что такое «инициализация нулем»?
203. Что является единицей памяти в С++? Какие требования к размеру единицы памяти прописаны в стандарте С++?
204. В каких единицах выдает результат операция sizeof? Какие типы данных имеют размер 1?
205. Какие три вида памяти входят в модель памяти С++?
206. Сколько видов динамической памяти обеспечивает С++?
207. Какие функции для работы с динамической памятью достались С++ по наследству от С? В какую библиотеку они включены?
208. Какие функции выделяют память, и с помощью каких функций память освобождается?
209. Какое важное отличие имеет функция calloc() от функции malloc()?
210. Какие действия выполняют функции выделения памяти, если память не может быть выделена?
211. Зависит ли объем выделенной памяти от типа указателя? Влияет ли выравнивание на объем выделяемой динамической памяти?
212. Можно ли с помощью функции realloc() уменьшить объем выделенной памяти?
213. Что произойдет, если функции free() передать в качестве аргумента нулевой указатель?
214. В чем главное отличие объектно-ориентированного механизма new/delete от механизма malloc()/free()?
215. Сколько существует форм new/delete? В чем их отличие?
216. Какие типы являются POD-типами? Чем отличается работа механизма new/delete с POD-объектами и nonPOD-объектами?
217. Какие функции выполняет обработчик new?
218. Можно ли реализовать собственный обработчик new и «прицепить» его к механизму new/delete?
219. В чем главное отличие объединения от других видов классов С++?
220. Может ли объединение участвовать в иерархии наследования?
221. Разрешается ли определять для объединения конструкторы и деструктор? А виртуальные функции?
222. В чем похожи и чем отличаются объединение и размещающий new?
223. Объясните, почему при использовании размещающего new нужно явным образом вызывать деструктор?
224. Зачем нужны интеллектуальные указатели?
225. Что такое «стратегия владения»? Сколько стратегий владения вы знаете?
226. Какой интеллектуальный указатель реализован в стандартной библиотеке STL, и какую стратегию владения он реализует?
227. Объясните, в чем преимущества и недостатки интеллектуальных указателей со счетчиком ссылок.
228. Разрешается ли перегружать new и delete и какими способами?
229. Опишите схему функции, перегружающей глобальную функцию new.
230. Отличается ли реализация перегруженной функции new[]() для массивов от реализации «обычной» функции new()?
231. Как вы думаете, почему функции new/delete, перегружаемые для класса, являются статическими?
232. Зачем при перегрузке new/delete для класса нужно проверять размер запрашиваемой памяти?
233. Объясните, чем определяется «динамичность» контейнеров?
234. Что такое «стратегия распределения памяти», и какие стратегии выделения памяти вы знаете?
235. Рассмотрите следующую стратегию распределения памяти: память выделяется для нескольких элементов блоками фиксированной длины, но блоки связываются в список. Для какого вида контейнера можно использовать такую стратегию?
236. Какие операции можно перегрузить для доступа к элементам двумерного массива?
237. В чем заключаются сложности использования операции индексирования [] для доступа к элементам двумерного массива?
238. Каковы способы реализации операций с контейнерами?
239. Какую конструкцию можно назвать «обобщенный алгоритм»?
240. Каким образом объявить указатель на метод?
241. Объясните разницу между указателем на функцию и указателем на метод.
242. Каким образом получить адрес метода?
243. Можно ли указателю на функцию присваивать адрес метода?
244. Какие операции определены в С++ для косвенного вызова метода через указатель?
245. Что такое «функтор»? Приведите пример функционального класса.
246. Какими способами функтор вызывается?
247. Можно ли использовать наследование при разработке функторов?
248. Разрешается ли операцию вызова функции () определять как виртуальный метод? А как статический?
249. В чем преимущества функторов перед указателями на функции?
250. Объясните, зачем нужны адаптеры функторов? Какие виды адаптеров вы знаете?
251. Как используются классы свойств при разработке функторов?
252. Объясните, что такое «композиция» и приведите примеры?
253. Объясните, чем отличается множественное наследование от простого?
254. Приведите структуру и принцип действия паттерна Adapter.
255. Сформулируйте основную проблему множественного наследования.
256. Выполняется ли принцип подстановки при открытом множественном наследовании?
257. Что такое виртуальное наследование? Каковы его преимущества и недостатки по сравнению с обычным наследованием?
258. Может ли виртуальное наследование быть одиночным?
259. Влияет ли виртуальное наследование на размер класса?
260. Объясните, каким образом с помощью виртуального наследования можно вообще запретить наследование.
261. Какие средства С++ составляют RTTI?
262. Объясните разницу между повышающим, понижающим и перекрестным приведением.
263. Какими свойствами должен обладать класс, чтобы с ним работал механизм RTTI?
264. В чем приведение указателей отличается от приведения ссылок?
265. Какие исключения связаны с механизмом RTTI?
266. Что такое «поток» — дайте определение.
267. Как классифицируются потоки, реализованые в библиотеках ввода/вывода С++?
268. Что такое буферизация и зачем она нужна?
269. Какие библиотеки ввода/вывода реализованы в С++ и чем они отличаются?
270. Перечислите стандартные потоки и объясните их назначение.
271. Зачем нужен процесс форматирования и когда он выполняется?
272. Что такое «форматная строка», и в каких функциях она используется?
273. Объясните назначение элементов спецификатора формата.
274. Сколько спецификаторов формата может быть в форматной строке?
275. Какой из элементов спецификатора формата не является умалчиваемым?
276. Перечислите несколько известных вам обозначений типов в спецификаторе формата, и укажите их назначение.
277. Сколько модификаторов типа вы знаете, и какую роль модификатор типа играет в спецификаторе формата?
278. С помощью какого флага можно выровнять выводимое значение влево? А каким образом вывести ведущие нули?
279. Какое действие оказывают на выводимую строку ширина, точнойть и флаги в спецификаторе формата?
280. Для чего в спецификаторе формата может использоваться символ звездочка («*»)? Чем отличается действие этого символа при воде и при выводе?
281. Каковы особенности ввода строк?
282. Каким образом ограничить набор вводимых символов при вводе?
283. Что является главной проблемой при использовании форматного ввода/вывода из библиотеки ?
284. Объясните, для чего нужны строковые потоки. Почему строковые потоки —всегда форматируемые?
285. С помощью каких функций выполняется работа со строковыми потоками?
286. Можно ли использовать тип string (и каким образом) со строковыми потоками?
287. Объясните, в чем заключается различие между текстовым и двоичным файлом.
288. Объясните, что означает «открыть» файл и «закрыть» файл?
289. Каким образом внешний файл связывается с потоком?
290. Можно ли один и тот же поток связать с разными файлами? А один и тот же файл с разными потоками?
291. Перечислите режимы открытия файла. Чем отличается режим “r” от режима “a”?
292. Какую роль в режиме открытия играет знак плюс («+»)?
293. В каких случаях необходимо следить за ситуацией «конец файла»? Каким способом это делается?
294. Можно ли текстовый файл открыть как двоичный? А двоичный — как текстовый?
295. Какие функции ввода/вывода используются для обмена с текстовыми файлами?
296. Перечислите функции ввода/вывода для работы с двоичными файлами.
297. Какие функции реализованы в библиотеке для обеспечения прямого доступа к записям двоичного файла? Можно ли их использовать для работы с текстовыми файлами?
298. Объясните назначение функции fseek().
299. Чем отличается функция ftell() от функции fgetpos()?
300. Объясните, что означает «перенаправление» потока? Какие потоки можно перенаправлять и куда?
301. Каким образом перенаправление ввода можно использовать для ввода строк с пробелами?
302. В чем преимущества объектно-ориентированной библитеки по сравнению с процедурной?
303. В каких состояних может находиться поток? Каким образом отслживается состояние «конец потока»?
304. Какие объектно-ориентированные потоки связаны со стандартными потоками?
305. Чем отличаются объектно-ориентированные строковые потоки от процедурных строковых потоков?
306. Каким образом строковые потоки можно использовать для ограничения ширины поля ввода? А можно ли с той же целью использовать строковые потоки ?
307. Сравните средства форматирования объектно-ориентированной и процедурной библиотеки.
308. Каким образом ввести строку типа string с пробелами?
309. Каково назначение флагов форматированя? Какие средства реализованы в библиотеке для работы с флагами форматирования?
310. Что такое «манипулятор»? В чем преимущества манипуляторов перед флагами форматирования?
311. Как связываются файлы с потоками в объектно-ориентированной библиотеке?
312. Можно ли файлы, записанные функциями библиотеки , прочитать объектно-ориентированными средствами? А наоборот?
313. Перечислите режимы открытия объектно-ориентированных файловых потоков. каким образом комбинируются режимы открытия файлоавых потоков?
314. Обязательно ли закрывать файл, связанный с объектно-ориентированным файловым потоком? А открывать?
315. Каким образом открыть файловый поток для чтения и записи одновременно?
316. Как открыть файловый поток для дозаписи?
317. Можно ли вывести значение переменной в двоичном виде и как это сделать?
318. Разрешается ли наследовать от классов библиотеки ввода/вывода?
319. Каким образом можно еренаправить объектно-ориентированный поток?
320. Как используется буфер потока для копирования потока?
321. Какими операциями выполняется форматированный ввод/вывод в файловые потоки? А неформатированный?
322. Реализованы ли в объектно-ориентированной библиотеке средства прямого доступа к файловым потокам? Сравните их с аналогичными средствами библиотеки .
323. С какими объектно-ориентированными потоками разрешается, и с какими не разрешается использовать средства прямого доступа?
324. Покажите, каким образом можно выполнить перегрузку операций ввода/вывода для нового типа данных.
325. Как выполняется обработка ошибок ввода/вывода в объектно-ориентированной библиотеке?
326. Какое стандартное исключение генерируется при ошибках ввода/вывода? Обязательно ли оно генерируется?
327. Чем стандартные широкие потоки отличаются от узких?
328. Что такое — «локаль», и каково ее назначение?
329. Как установить русский шрифт при выводе в консольное окно?
330. Чем отличается ли ввод/вывод широких файловых потоков от узких?
331. Перечислите все последовательные контейнеры стандартной библиотеки. Чем они отличаются друг от друга?
332. Перечислите адаптеры последовательных контейнеров и дайте их подробную характеристику.
333. Почему для адаптеров-очередей нельзя использовать вектор в качестве базового?
334. Чем простая очередь queue отличается от приоритетной очереди priority_queue?
335. Каким требованиям должны удовлетворять элементы контейнера?
336. Могут ли быть указатели элементами контейнера? А итераторы?
337. Почему нельзя использовать в качестве элементов контейнера стандартный интеллектуальный указатель auto_ptr?
338. Зачем в контейнере list реализованы собственные методы сортировки поиска и слияния? Можно ли пользоваться соответствующими стандартными алгоритмами при обработке списка?
339. Перечислите типовые виды конструкторов, с помощью которых можно создавать последовательный контейнер.
340. Можно ли инициализировать контейнер элементами встроенного массива? А элементами другого контейнера? Какими способами это можно сделать?
341. Почему конструктор инициализации, параметрами которого являются итераторы, сделан шаблонным во всех контейнерах?
342. Какие методы реализованы в контейнере-векторе для доступа к элементам?
343. Отличается ли функция at() доступа по индексу от перегруженной операции индексирования и чем?
344. Перечислите методы контейнера deque, относящиеся к определению размеров контейнера.
345. Чем метод size() отличается от метода capacity()? А в чем отличие этих методов от метода max_size()?
346. Перечислите методы контейнера list, предназначенные для вставки удаления и замены элементов. Отличаются ли эти методы от соответствующих методов вектора и дека?
347. Каким образом выполняются операции сравнения контейнеров?
348. Разрешается ли изменять элемент ассоциативного контейнера, доступный в данный момент по итератору?
349. Какие контейнеры называются ассоциативными и почему?
350. Чем контейнер map отличается от контейнера multimap?
351. Объясните, почему в ассоциативных контейнерах нельзя изменять элемент, доступный в данный момент по итератору.
352. По каким причинам в контейнере-множестве не реализованы типовые операции объединения, пересечения, разности и другие?
353. Как используется структура-пара в ассоциативных контейнерах?
354. Объясните, что такое «критерий сортировки», и каким требованиям он должен удовлетворять? Какой критерий сортировки принят по умолчанию?
355. Какими преимуществами обладает функция make_pair() по сравнению с конструктором pair()?
356. Почему в контейнерах-отображениях операция индексирования перегружена, а в контейнерах-множествах — нет?
357. Какие гарантии безопасности обеспечивают контейнеры стандартной библиотеки?
358. Что такое «транзакционная гарантия безопасности» и чем она отличается от базовой?
359. На какие 4 класса по надежности можно разделить все операции с контейнерами?
360. Что такое «распределитель памяти» и зачем он нужен?
361. Чем отличается битовый вектор bitset от битового вектора vector?
362. Дайте определение итератора.
363. Что такое «начальный» итератор и «конечный» итератор? Какие методы, связанные с итераторами, обязательно включает каждый контейнер?
364. Чем константный итератор отличается от неконстантного?
365. Объясните, что такое «недействительный» итератор. В каких случаях итераторы становятся недействительными?
366. Какие категории итераторов вы знаете? Какие операции обязательно реализуются для всех категорий итераторов?
367. К какому виду итераторов можно отнести встроенный указатель и почему?
368. Какие вспомогательные функции для итераторов вы знаете? В каких случаях оправдано их применение?
369. Какие адаптеры итераторов реализованы в библиотеке?
370. Объясните, почему итераторы реализованы как вложенные классы в контейнерах.
371. Чем отличаются итераторы вставки от обычных итераторов?
372. Каким образом используются потоковые итераторы?
373. Какие стандартные функторы реализованы в библиотеке STL? Каково их основное назначение?
374. Для чего нужны адаптеры функторов bind1st() и bind2nd()?
375. Как применяются адаптеры-отрицатели?
376. Почему алгоритмы remove() не удаляют элементы из контейнеров? Как реально удалить элементы из контейнера?
377. Чем отличается стабильная сортировка от обычной?
378. Какую функцию выполняет алгоритмы unique()?
379. Могут ли стандартные алгоритмы работать со строками?
380. Нужно ли сортировать ассоциативные контейнеры?
381. Можно ли алгоритмы для работы с множествами применять для последовательных контейнеров? При каких условиях?
382. Какие алгоритмы предназначены для заполнения контейнера значениями? С какими контейнерами они могут работать?
383. Каким образом заполнить с помощью алгоритма generate() последовательный контейнер, не имеющий ни одного элемента?
384. Перечислите алгоритмы, предназначенные для операций с каждым элементом контейнера.
385. Можно ли с помощью алгоритма for_each() изменить элементы контейнера?

 

Зеркало этого блога на Я.ру


Друзья, теперь вы можете читать и комментировать мои записи и на Я.ру — Мурат Джусупов!
 

Использование pthread (POSIX) функций для многопоточных iPhone-приложений


Оказывается, перед использованием pthread (POSIX) функций очень важно дать знать Cocoa о том, что в программе будут присутствовать дополнительные потоки.

Для этого достаточно создать один дополнительный поток с помощью класса NSThread и тут же позволить ему завершиться (т.е. не создаваться бесконечный цикл, а просто создать пустую функцию, которая должна запуститься в этом отдельном потоке).

После этого Cocoa будет знать, что запущенное приложение не однопоточное.

Информация была прочитана из сайта http://developer.apple.com

 

Xcode — странные выходки отладчика


Отладчик, встроенный в Xcode, иногда вытворяет казалось бы необъяснимые вещи. Например, указатель согласно показаниям отладчика может быть равен нулю в том месте кода, где до этого была проверка, согласно которой в случае нулевого значения указателя код не должен дальше выполняться. Или бывает так, что строка приобретает зловещий вид через некоторое время после её инициализации (этот вид можно увидеть в Memory Browser).

Эти странные выходки Xcode-отладчика возникают по 2-м причинам, которые я успел уже выяснить:

1) Либо какая-то часть бинарного кода статической библиотеке не соответствует исходникам этой библиотеки (иначе говоря, исходники могли поменяться, а библиотеку забыли перекомпилировать).

2) Либо происходит обыкновенное переполнение стека. Тогда отладчик начинает показывать странные значения переменных. По крайней мере, на моей работе такое произошло в дополнительно созданном потоке. С помощью pthread-функций или с помощью класса NSThread можно изменять размер стэка потока перед его созданием потока, так как по умолчанию размер стека равен 512 килобайт. Благо, рядом со мной оказались опытные программисты. Они подсказали, что при переполнениях стека отладчик происходит повреждение данных, поэтому отладчик и показывает всякую чушь

 

Проблемы со статическими библиотеками при разработке iPhone-приложений


Если в приложении используется несколько статических библиотек (имеющих расширение.a), то иногда сборка приложения при изменении некоторых библиотек превращается в сущий кошмар.

Вот что мне удалось выяснить опытным путём, потратив на это многие часы.

1) Если что-то изменяется в одной из библиотек, от которой зависят одна или несколько других библиотек, то лучше всего сразу же радикально уничтожить не только сами устаревшие бинарные файлы этих библиотек, но и все промежуточные объектные файлы.

2) При переходе с Debug на Release или обратно разработчики нередко удаляют для подстраховки ненужные библиотеки (например из дерева проекта удаляют Debug-версии статических либ и добавляют Release-версии тех же самых статических либ, т.е. библиотек). Я поддерживаю такое решение, так как невозможно определённо сказать, будет ли Xcode правильно подбирать нужную либу из 2-х вариантов при сборке приложения. Увы, это уже подтверждается опытом. Но оказывается этой меры недостаточно! Нужно либо физически удалить ставшие ненужными (даже ненужными на время) бинарные файлы библиотек, либо просто переместить их в другое место (или хотя бы переименовать папку, где они были собраны в одном месте). Оказывается, часто случается так, что Xcode упорно отказывается линковать к приложению указанную в дереве проекта нужную вам библиотеку (например, Release) и линкует ту прежнюю библиотеку, которую вы уже убрали из дерева проекта. НО И ЭТОГО БЫВАЕТ МАЛО!!! Нужно удалять даже промежуточные объектные файлы (особенно в случаях, когда вы решили вообще отказаться использовать какую-то библиотеку, переместив её код непосредственно в проект.

Очень надеюсь, что Apple когда-нибудь исправит эти баги в Xcode (или в iPhone SDK).

 

Переименование Xcode-проекта и приложения (для iPhone)


Можно легко переименовывать основной контейнер проекта (который в Windows/Unix выглядит как обычная папка, а в Finder из Mac OS выглядит внешне как файл с расширением *.xcodeproj) - обычно это не вызывает никаких проблем.

Это может пригодиться, если вы делаете в Xcode приложение или библиотеку для Mac OS и для iPhone, используя общие исходные файлы. В таком случае достаточно сделать копию *.xcodeproj-контейнера и дать ему другое имя.

Несколько иначе обстоит дело при попытке изменить имя приложения для iPhone, т.е. название программы, как оно отображается в списке приложений на экране iPhone. Сейчас в новой версии iPhoneSDK в меню Xcode есть возможность переименовать проект (и вероятно название программы) - но я пока не исследовал эту возможность.

Далее я расскажу про старый способ переименовать проект, который я уже проверил несколько раз (об этом я узнал из зарубежных источников).

Скопируйте папку всего проекта (не только вышеупомянутый контейнер с расширением *.xcodeproj, но и все исходники с ресурсами) в надёжное место — вдруг что-то получится не так, как вы хотели. Вообще, полезно всегда делать копии всех важных файлов как можно чаще (или использовать систему контроля версий).

Войдите в ту папку, в которой вы будете переименовывать проект. Давайте будем считать для примера, что мы хотим переименовать AppleSample в MyCoolApp.

1) Переименуйте AppleSample.xcodeproj в MyCoolApp.xcodeproj.
2) Переименуйте AppleSample_Prefix.pch в MyCoolApp_Prefix.pch
3) Удалите папку build folder (используя Finder).
4) Откройте.xcodeproj как контейнер-папку (используя контекстное меню, например нажав на правую кнопку мыши, в зависимости от настроек Mac OS). В этой папке есть несколько файлов (обычно 3 или 4). Их нужно будет редактировать в текстовом редакторе (желательно с подсветкой синтаксиса для вашего же удобства — можно открыть даже с помощью Xcode).
5) Откройте project.pbxproj как текст и переименуйте все встречающиеся строки со старым именем AppleSample на новое имя MyCoolApp. Лучше не используйте для этого операцию «Найти и заменить (find an replace)». Имейте ввиду, что если вы захотите изменить строки, содержащие AppleSampleAppDelegate.h и AppleSampleAppDelegate.m, то изменение этих строк вынудит вас переименовать файлы с этими именами физичеки (поменять имена на те, что вы укажете в строках вместо старых).
6) Откройте файл с расширением.pbxuser (имя этого файла содержит ваше системное имя пользователя). Повторите все предыдущие шаги по редактированию строк.
7) Откройте все xib-файлы (их ещё принято называть nib-файлами) как текстовые или source файлы и повторите все предыдущие шаги по редактированию строк (это особенно актуально, если вы осмелились переименовать исходники главного делегата приложения).
8) Попробуйте после всего этого открыть проект в Xcode, и сделайте Clean и Build.

1 |2 |3 |4 |5

     
ЯнварьФевральМартАпрельМайИюньИюльАвгустСентябрьОктябрьНоябрь (82)Декабрь
           
123456789101112131415161718192021222324252627282930