dxp 58 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба Хе, еще хуже. Компиллер создает в bss переменную-флаг был ли создан обьект или нет. Далее он проверяет этот флаг. если он не установлен - вызывает функцию __cxa_guard_acquire, которая должна заблокировать этот обьект(типа открыть мютекс) и далее запускает конструктор. потом вызывает __cxa_guard_release и возвращает указатель/ссылку на обьект. :) Естественно, это стандартная реализация инициализации статических объектов функции (а блокировка зависит от того thread safe этот код или нет). Ессно тело этих функций лежит на нас. Это почему это? Компилятор делает это самостоятельно и совершенно прозрачно от программиста, в этом и преимущество. И ессно это гемор, проще вызвать init(...) в нужном месте і все Вообще-то, приведённый код - это реализация паттерна Singleton. Очень хорошая штука к месте. Применяется, главным образом, для борьбы с зависимостью от порядка компиляции объектов. Большого оверхеда не тянет. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба Большинство объектов в программе, как правило, не привязаны к аппаратуре, для них можно спокойно использовать конструкторы без ограничений. обьекты, выделены статически, в той или иной мере зависят от состояния ОС, если в них используются ее функции. а большинсво они такие и есть(тк глобальный обьект - должен быть 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 никак проблем не создаст. а если его забыть, то прога ляжет сразу и ошибка найдется легко. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба init никак проблем не создаст. а если его забыть, то прога ляжет сразу и ошибка найдется легко. Вовсе не обязательно. У нас в одном проекте через месяц программист нашел эту ошибку. А до этого все как-то жило себе и ничего. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба Естественно, это стандартная реализация инициализации статических объектов функции (а блокировка зависит от того thread safe этот код или нет). конечно thread-safe, иначе запарки с конструкторами небыло бы, вернее с необходимостю явного вызова конструктора, переименованного в init(..);. Это почему это? Компилятор делает это самостоятельно и совершенно прозрачно от программиста, в этом и преимущество. и от куда он знает как у нас реализована блокировак и как ею пользоватся? по моему он никак не догадывается, что у меня есть функции CreateKernelObject(MUTEX_TYPE),OpenMutex(ko),CloseMutex(ko) итд... Вовсе не обязательно. У нас в одном проекте через месяц программист нашел эту ошибку. А до этого все как-то жило себе и ничего. Заполните .bss каким-нибдь криптографическим рандомом :D (кроме шуток) и бага вылезет моментально :) Применяется, главным образом, для борьбы с зависимостью от порядка компиляции объектов. Большого оверхеда не тянет. Чет не вьехал.. что за зависимость от порядка компиляции обьектов и когда она возникает? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DimaG 0 22 сентября, 2011 Опубликовано 22 сентября, 2011 (изменено) · Жалоба Компилятор ничего не знает о потоках, процессах и тд! Ни PC, ни эмбеддед. Соответственно, никаких блокировок не должен использовать. Singleton - удобный способ создания одного(И только одного) объекта класса. Если на пальцах - при первом вызове "псевдоконструктора" происходит создание объекта, при последующих - возвращается ссылка на первый объект. Помимо этого у него ест еще одно полезное свойство - не нужно хранить указатель на объект. Мы его получаем по имени класса. По поводу порядка инициализации. Порядок инициализации объектов определен лишь в пределах одной единицы трансляции. Соответственно, имя два cpp файла нельзя сказать, статические переменные какого файла будут проинициализированны первыми. Я с этим борюсь так: у каждого сервиса есть 4 унаследованных метода: Init, Run, Stop, Done. Рассылкой multcast сообщений я их по очереди вызываю. Те сначала вызываются все методы Init, потом все методы Run и тд. Это вызывается лишь в одном месте программы, тем самым избегаю случая "забывания вызывания Init" Вот моя реализация синглтона ///@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; } Изменено 22 сентября, 2011 пользователем IgorKossak [codebox] Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба Компилятор ничего не знает о потоках, процессах и тд! Ни PC, ни эмбеддед. Соответственно, никаких блокировок не должен использовать. Qt+gcc еще как знает :) Я с этим борюсь так: у каждого сервиса есть 4 унаследованных метода: Init, Run, Stop, Done. Рассылкой multcast сообщений я их по очереди вызываю. Те сначала вызываются все методы Init, потом все методы Run и тд. Это вызывается лишь в одном месте программы, тем самым избегаю случая "забывания вызывания Init" зависит от конкретной реализации. в моем случае проще,безопаснее вызвать конструктор явно в нужном месте, чем городить какие-то хитрые конструкции только ради саих этих конструкций и авто-вызова конструктора. забыть вызвать (псевдо)конструктор довольно сложно, тк он асоциирован с подключением конкретного модуля(если я юзаю usb-msc, как же я могу забыть его проинициализироват? а он сам в свою очередь унаследован от usb,и других классов выше, и сам вызовет нужные псевдо-конструкторы по иерархии) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DimaG 0 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба Qt+gcc еще как знает :) Лично налетал на гонки в синглтоне. Компилятор gcc. Возможно, я просто не умею его готовить.. Но - осадочек остался. Сейчас только критическая секция. зависит от конкретной реализации. Я бы сказал - зависит от подхода. :) Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
sergeeff 1 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба Qt+gcc еще как знает :) зависит от конкретной реализации. в моем случае проще,безопаснее вызвать конструктор явно в нужном месте, чем городить какие-то хитрые конструкции только ради саих этих конструкций и авто-вызова конструктора А кто мешает в этом самом нужном месте вызвать: Class *pAAA = new AAA; Вызывается сам конструктор, а не какой-то там Init(). Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
777777 0 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба Правда? Т.е. сами по себе классы нафиг не нужны? И перегрузка имён функций/операторов не нужна? И возможность объявлять объекты в любом месте программы не нужна? И наследование (без виртуальных функций) не нужно? И шаблоны не нужны? Что значит "не нужны"? Что значит "сами по себе"? (почти) всё перечисленное - свойства ООП. Поскольку все это есть в С++, то он является объектно-ориентированным языком. Да будет вам известно, что исходно С++ появился именно как объектный язык, и ОО составляющая была в него добавлена значительно (годы) позже. Мне кажется при построении этого предложения вы где-то допустиои опечатку. С++ никогда не был чистым ОО языком - ООП в нём - это лишь один (и не очень обширный) из его аспектов. Изначально он назывался "Си с классами". Потом он получил название С++, а постепенно в него напихали всего, что было модно на текущем этапе развития программирования. Поэтому трудно говорить о том, был ли он когда-нибудь "чистым" ОО языком весьма проблематично. Либо (если не согласны в вышеперечисленным) вы не вполне понимаете, что такое ООП. Я понимаю, фаллометрия очень важна для посетителей этого форума. Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба Лично налетал на гонки в синглтоне. Компилятор gcc. Возможно, я просто не умею его готовить.. Но - осадочек остался. Сейчас только критическая секция. посему я предпочитаю ручной контроль thread-safety Class *pAAA = new AAA; Вызывается сам конструктор, а не какой-то там Init(). а реализовывать оператор new кто будет? и какими средствами и зачем, на платформе с 64кб оперативки, половина которой ушла под буфферы и стеки... Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба еще вопрос по поводу реюза кода. Как, на пример, в 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 при чем, с возможностью наследования Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
AHTOXA 18 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба Нужно, его так заточить, чтобы разные экземпляры его обьектов были в разных секциях... -fdata-sections? Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба а код? -ffunction-sections , а потом это все вручную собирать в линкер-скрипте...проще уж хедеры править Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
brag 0 22 сентября, 2011 Опубликовано 22 сентября, 2011 · Жалоба Реализовал через манипуляцию ld -r, линкер-скрипты, objcopy -G Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться
DimaG 0 23 сентября, 2011 Опубликовано 23 сентября, 2011 · Жалоба а реализовывать оператор new кто будет? и какими средствами и зачем, на платформе с 64кб оперативки, половина которой ушла под буфферы и стеки... Почитайте про "Placement new". Это прояснит многие вопросы, в том числе и про выделение в разных секциях Цитата Поделиться сообщением Ссылка на сообщение Поделиться на другие сайты Поделиться