|
|
  |
Как писать на С++ при создание приложений под ARM, Примеры |
|
|
|
Sep 22 2011, 13:19
|

Adept
     
Группа: Свой
Сообщений: 3 469
Регистрация: 6-12-04
Из: Novosibirsk
Пользователь №: 1 343

|
Цитата(brag @ Sep 22 2011, 20:13)  Хе, еще хуже. Компиллер создает в bss переменную-флаг был ли создан обьект или нет. Далее он проверяет этот флаг. если он не установлен - вызывает функцию __cxa_guard_acquire, которая должна заблокировать этот обьект(типа открыть мютекс) и далее запускает конструктор. потом вызывает __cxa_guard_release и возвращает указатель/ссылку на обьект.  Естественно, это стандартная реализация инициализации статических объектов функции (а блокировка зависит от того thread safe этот код или нет). Цитата(brag @ Sep 22 2011, 20:13)  Ессно тело этих функций лежит на нас. Это почему это? Компилятор делает это самостоятельно и совершенно прозрачно от программиста, в этом и преимущество. Цитата(brag @ Sep 22 2011, 20:13)  И ессно это гемор, проще вызвать init(...) в нужном месте і все Вообще-то, приведённый код - это реализация паттерна Singleton. Очень хорошая штука к месте. Применяется, главным образом, для борьбы с зависимостью от порядка компиляции объектов. Большого оверхеда не тянет.
--------------------
«Отыщи всему начало, и ты многое поймёшь» К. Прутков
|
|
|
|
|
Sep 22 2011, 13:32
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
Цитата Большинство объектов в программе, как правило, не привязаны к аппаратуре, для них можно спокойно использовать конструкторы без ограничений. обьекты, выделены статически, в той или иной мере зависят от состояния ОС, если в них используются ее функции. а большинсво они такие и есть(тк глобальный обьект - должен быть thread-safe обьект) потому так и получается, что в embedded-проекте все оно под одну гребенку для статика. выделять под каждый кусок проекта отдельные секции тоже не в кайф и не всегда катит - у тредов есть shared-memory... Цитата 256 кБ - весьма приличный объём, если писать код своими руками (а не забить его библиотечными функциями). А по меркам embedded так даже и нифига себе. да ну. TwoFish,RSA-2048,ECDSA,sha-256,дрова(включая usb-msc,usb-cdc,transflash,всякие там верхнего уровня прибамбасики типа акселерометра с простенькими dsp-алго),всякие там парсеры и немного полезного(не служебного) кода - 110кб сожрало. при чем все ручками, ни единой библиотечной функции,каждый алго вылизивался руками для достижения требуемых условий по производительности. и это нету еще gui с кучей текста(пусть даже на одном инглише,не говоря о 2-3 языках) Цитата Rvalue reference - это совсем не те ссылки, которые в нынешнем С++. Это совсем другая штука. Обычные ссылки, кстати, тоже, имхо, зря обделяете вниманием - они в ряде случаев дают более простую семантику и более безопасный код. разеремся,как поддержка нормальная появится  Цитата init() обладает одним существенным недостатком - нужно не забывать корректировать его при изменениях в совсем других частях программы. зачем? раз его реализовал, равно как и конструктор и вызываешь где нужно. Цитата В общем, это в значительной степени отказ от идеи абстракции (и инкапсуляции) данных в виде законченных объектов, т.е. в некотором роде даунгрейд в С. По мере роста сложности программ, это не добавляет радости. немного да, помнить все же про обьект(но никак не про внутренности класса,что уже не трогает инкапсуляцию) нужно будет. и вызвать init перед первым его использованием. в embedded надо помніть о гораздо более важных и запутанных вещах, что init никак проблем не создаст. а если его забыть, то прога ляжет сразу и ошибка найдется легко.
|
|
|
|
|
Sep 22 2011, 13:41
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
Цитата Естественно, это стандартная реализация инициализации статических объектов функции (а блокировка зависит от того thread safe этот код или нет). конечно thread-safe, иначе запарки с конструкторами небыло бы, вернее с необходимостю явного вызова конструктора, переименованного в init(..);. Цитата Это почему это? Компилятор делает это самостоятельно и совершенно прозрачно от программиста, в этом и преимущество. и от куда он знает как у нас реализована блокировак и как ею пользоватся? по моему он никак не догадывается, что у меня есть функции CreateKernelObject(MUTEX_TYPE),OpenMutex(ko),CloseMutex(ko) итд... Код Вовсе не обязательно. У нас в одном проекте через месяц программист нашел эту ошибку. А до этого все как-то жило себе и ничего. Заполните .bss каким-нибдь криптографическим рандомом :D (кроме шуток) и бага вылезет моментально  Цитата Применяется, главным образом, для борьбы с зависимостью от порядка компиляции объектов. Большого оверхеда не тянет. Чет не вьехал.. что за зависимость от порядка компиляции обьектов и когда она возникает?
|
|
|
|
|
Sep 22 2011, 14:38
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Компилятор ничего не знает о потоках, процессах и тд! Ни PC, ни эмбеддед. Соответственно, никаких блокировок не должен использовать. Singleton - удобный способ создания одного(И только одного) объекта класса. Если на пальцах - при первом вызове "псевдоконструктора" происходит создание объекта, при последующих - возвращается ссылка на первый объект. Помимо этого у него ест еще одно полезное свойство - не нужно хранить указатель на объект. Мы его получаем по имени класса. По поводу порядка инициализации. Порядок инициализации объектов определен лишь в пределах одной единицы трансляции. Соответственно, имя два cpp файла нельзя сказать, статические переменные какого файла будут проинициализированны первыми. Я с этим борюсь так: у каждого сервиса есть 4 унаследованных метода: Init, Run, Stop, Done. Рассылкой multcast сообщений я их по очереди вызываю. Те сначала вызываются все методы Init, потом все методы Run и тд. Это вызывается лишь в одном месте программы, тем самым избегаю случая "забывания вызывания Init" Вот моя реализация синглтона CODE ///@class TClSingleton ///@brief Use access to object instance. ///After first call Instance() method, create instance of object. ///All next call Instance() method will return pointer to first object ///Typical use: /// <pre> ///@code ///class SignleObject: public TClSigneton<SingleObject> ///{ /// friend class TClSigneton<SingleObject>; /// . . . . . /// protected: /// SignleObject(); ///} ///...... ///SignleObject* pclObject_ = SignleObject::Instance(); // Will be created object, or return pointer on early created oblect ///...... ///@endcode /// </pre> template <class ClSignleObject> class TClSingleton { public: /// Static method. Will be used in inheritor /// @return Pointer to object instance inline static ClSignleObject* Instance();
protected: /// Protected default constructor TClSingleton(){} };
///@brief Realization of instance() method template <class ClSignleObject> inline ClSignleObject* TClSingleton<ClSignleObject>::Instance() { TClCriticalSection<true> clCS_;
static ClSignleObject* pclInstance_s = new ClSignleObject(); return pclInstance_s; }
Сообщение отредактировал IgorKossak - Sep 22 2011, 15:56
Причина редактирования: [codebox]
|
|
|
|
|
Sep 22 2011, 15:05
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
Цитата Компилятор ничего не знает о потоках, процессах и тд! Ни PC, ни эмбеддед. Соответственно, никаких блокировок не должен использовать. Qt+gcc еще как знает  Цитата Я с этим борюсь так: у каждого сервиса есть 4 унаследованных метода: Init, Run, Stop, Done. Рассылкой multcast сообщений я их по очереди вызываю. Те сначала вызываются все методы Init, потом все методы Run и тд. Это вызывается лишь в одном месте программы, тем самым избегаю случая "забывания вызывания Init" зависит от конкретной реализации. в моем случае проще,безопаснее вызвать конструктор явно в нужном месте, чем городить какие-то хитрые конструкции только ради саих этих конструкций и авто-вызова конструктора. забыть вызвать (псевдо)конструктор довольно сложно, тк он асоциирован с подключением конкретного модуля(если я юзаю usb-msc, как же я могу забыть его проинициализироват? а он сам в свою очередь унаследован от usb,и других классов выше, и сам вызовет нужные псевдо-конструкторы по иерархии)
|
|
|
|
|
Sep 22 2011, 15:16
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Цитата(brag @ Sep 22 2011, 22:05)  Qt+gcc еще как знает  Лично налетал на гонки в синглтоне. Компилятор gcc. Возможно, я просто не умею его готовить.. Но - осадочек остался. Сейчас только критическая секция. Цитата(brag @ Sep 22 2011, 22:05)  зависит от конкретной реализации. Я бы сказал - зависит от подхода.
|
|
|
|
|
Sep 22 2011, 15:21
|
Профессионал
    
Группа: Свой
Сообщений: 1 481
Регистрация: 10-04-05
Пользователь №: 4 007

|
Цитата(brag @ Sep 22 2011, 18:05)  Qt+gcc еще как знает  зависит от конкретной реализации. в моем случае проще,безопаснее вызвать конструктор явно в нужном месте, чем городить какие-то хитрые конструкции только ради саих этих конструкций и авто-вызова конструктора А кто мешает в этом самом нужном месте вызвать: Код Class *pAAA = new AAA; Вызывается сам конструктор, а не какой-то там Init().
|
|
|
|
|
Sep 22 2011, 15:40
|

Профессионал
    
Группа: Участник
Сообщений: 1 091
Регистрация: 25-07-07
Из: Саратов
Пользователь №: 29 357

|
Цитата(dxp @ Sep 22 2011, 11:25)  Правда? Т.е. сами по себе классы нафиг не нужны? И перегрузка имён функций/операторов не нужна? И возможность объявлять объекты в любом месте программы не нужна? И наследование (без виртуальных функций) не нужно? И шаблоны не нужны? Что значит "не нужны"? Что значит "сами по себе"? (почти) всё перечисленное - свойства ООП. Поскольку все это есть в С++, то он является объектно-ориентированным языком. Цитата(dxp @ Sep 22 2011, 11:25)  Да будет вам известно, что исходно С++ появился именно как объектный язык, и ОО составляющая была в него добавлена значительно (годы) позже. Мне кажется при построении этого предложения вы где-то допустиои опечатку. Цитата(dxp @ Sep 22 2011, 11:25)  С++ никогда не был чистым ОО языком - ООП в нём - это лишь один (и не очень обширный) из его аспектов. Изначально он назывался "Си с классами". Потом он получил название С++, а постепенно в него напихали всего, что было модно на текущем этапе развития программирования. Поэтому трудно говорить о том, был ли он когда-нибудь "чистым" ОО языком весьма проблематично. Цитата(dxp @ Sep 22 2011, 11:25)  Либо (если не согласны в вышеперечисленным) вы не вполне понимаете, что такое ООП. Я понимаю, фаллометрия очень важна для посетителей этого форума.
|
|
|
|
|
Sep 22 2011, 16:09
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
Цитата Лично налетал на гонки в синглтоне. Компилятор gcc. Возможно, я просто не умею его готовить.. Но - осадочек остался. Сейчас только критическая секция. посему я предпочитаю ручной контроль thread-safety Цитата Class *pAAA = new AAA; Вызывается сам конструктор, а не какой-то там Init(). а реализовывать оператор new кто будет? и какими средствами и зачем, на платформе с 64кб оперативки, половина которой ушла под буфферы и стеки...
|
|
|
|
|
Sep 22 2011, 17:45
|
Профессионал
    
Группа: Свой
Сообщений: 1 047
Регистрация: 2-12-06
Из: Kyiv, Ukraine
Пользователь №: 23 046

|
еще вопрос по поводу реюза кода. Как, на пример, в gcc, сделать так, чтобы без модификации исходного кода пихать код и данные в разные секции? На пример, есть такой класс Код class Twofish{ public: void Key(const U32 *key32); void Encrypt(U32 *oblk32,const U32 *iblk32,U32 nblocks,U32 *iv32); void Decrypt(U32 *oblk32,const U32 *iblk32,U32 nblocks,U32 *iv32); private: U32 sboxKey[TWF_KEY_BITS/64]; struct{ U32 inWhiten[TWF_BLOCK_BITS/32]; // input/output whitening U32 outWhiten[TWF_BLOCK_BITS/32]; U32 round[2*TWF_ROUNDS]; // round subkeys }subKeys; }; Нужно, его так заточить, чтобы разные экземпляры его обьектов были в разных секциях... скажем есть в одном файле Twofish twf1; в другом Twofish twf2; надо, чтобы : код twf1 лежал в секции .text данные twf1 лежали в секции .bss код twf2 лежал в секции .text1 данные twf2 лежали в секции .kbss2 при чем, с возможностью наследования
|
|
|
|
|
Sep 23 2011, 04:30
|
Местный
  
Группа: Свой
Сообщений: 279
Регистрация: 2-07-08
Из: Новосибирск
Пользователь №: 38 699

|
Цитата(brag @ Sep 22 2011, 23:09)  а реализовывать оператор new кто будет? и какими средствами и зачем, на платформе с 64кб оперативки, половина которой ушла под буфферы и стеки... Почитайте про "Placement new". Это прояснит многие вопросы, в том числе и про выделение в разных секциях
|
|
|
|
|
  |
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0
|
|
|