Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Правила High Integrity C Coding Standart

Anna | 24.06.2014 | нет комментариев
Десять лет назад возникла первая редакция High Integrity C Coding Standart. К тому времени С был теснее пять лет как стандартизирован ISO и примерно двадцать лет применялся в индустрии. Это был соверешенно зрелый язык с широким сообществом профессиональных и не только разработчиков. Сообщество это собрало довольно приколов про расстрелянные ноги, Дабы в нем созрела идея о создании эталона ограничений — перечня того, чего в языке делать не следует.

К тому времени теснее существовали сходственные эталоны, но они как правило были закрыты и малоизвестны. HICPP, изданный компанией Programming Research Ltd, стал первым открытым эталоном высококачественного программирования на языке С . Чуть позднее к нему присоединились JSF AV C , открытый компанией Локхид-Мартин и MISRA-C :2008 Заокеанской ассоциации безопасности автомобильной индустрии. Из этой тройки HICPP остается особенно знаменитым среди широкой публики.Конструктивно HICPP — это приблизительно две сотни правил и рекомендаций, всякое из которых разрешает избежать тупых ошибок при применении того либо другого аспекта языка. К всякому правилу прилагается пояснение, изредка сопровождаемое примером кода, список исключений и ссылка на тот либо другой источник. Все совместно — 84 страницы мозгодробительного текста, с которым весьма желанно ознакомиться каждому, кто не хочет переизобрести все эти правила одно за одним на основе личного грустного навыка.

Данный перевод предназначается экстраординарно для поверхностного ознакомления и содержит только текст самих правил без пояснений и примеров. Полный текст эталона на языке оригинала доступен по адресу:http://www.codingstandard.com/HICPPCM/

Всеобщие правила

Правило 2.1 Все отклонения от правил эталона обязаны быть детально прокомментированы в коде.

Рекомендация 2.2 Компилятор стоит настроить так, Дабы «char» реализовывался как «unsigned char».

Классы: всеобщие правила

Правило 3.1.1 Члены класса следует определять в порядке, соответствующем ярусу доступа: вначале «public», потом «protected», последними «private».

Правило 3.1.2 Экземпляры класса стоит определять напрямую конструктором, а не копирующим конструктором через присвоение.

Правило 3.1.3 Для классов, которые руководят источниками, нужно определить конструтор копирования, оператор присвоения и деструктор.

Правило 3.1.4 Для определения конструктора присвоения используйте атомарную не генерирующую исключения операцию «swap».

Правило 3.1.5 Оператор присвоения должен быть реализован правильно касательно самоприсвоения, наследования, управления источниками и консистентно касательно присвоения по умолчанию.

Правило 3.1.6 Не объявляйте виртуальные функции инлайнами.

Рекомендация 3.1.7 Не объявляйте способы класса инлайнами, взамен этого определяйте их в теле класса.

Правило 3.1.8 Все способы, которые не изменяют видимое извне состояние объекта, обязаны быть определены константными.

Рекомендация 3.1.9 Всякое определенное поведение должно быть определено только в одном способе класса.

Правило 3.1.10 Не определяйте операторы конвертации к фундаментальным типам.

Правило 3.1.11 Не определяйте операторы конвертации к классам.

Рекомендация 3.1.12 Обеспечьте оператор итога в поток “<<” для всякого класса.

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

Классы: конструкторы и деструкторы

Правило 3.2.1 Все конструкторы обязаны предоставлять исходное значение (либо вызывать в свою очередь конструкторы) для всякого виртуального базового класса, всякого невиртуального базового класса и всякого нестатического члена.

Правило 3.2.2 Записывайте члены класса в списке инициализации в том же порядке, в каком они объявляются.

Правило 3.2.3 Определяйте все конструкторы с одним доводом как «explicit» (за исключением копирующего конструктора).

Рекомендация 3.2.4 Отвлеченный класс не должен иметь публичных конструкторов.

Правило 3.2.5 Деструкторы обязаны освобождать все источники, принадлежащие объекту.

Рекомендация 3.2.6 Не объявляйте конструкторы и деструкторы инлайнами.

Классы: наследование

Правило 3.3.1 Деривация должна быть экстраординарно публичной.

Правило 3.3.2 Определяйте виртуальные деструкторы для базовых классов.

Правило 3.3.3 Избегайте приведения указателей базового класса к указателям наследованного.

Правило 3.3.4 Избегайте приведения к виртуальному базовому классу, это необратимо (для приведения вниз по иерархии возможно применять «dynamic_cast», но это требует RTTI и сопряжено соответствующим оверхедом).

Правило 3.3.5 Переопределяйте все перегрузки виртуальных способов базового класса.

Правило 3.3.6 Если вирутальная функция базового класса не переопределена ни в одном наследующем классе, она не должна быть виртуальной.

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

Правило 3.3.8 Если всякий наследующий класс предоставляет собственную неповторимую реализацию виртуальной функции базового класса, то функция базового класса должна быть чистой вирутальной.

Правило 3.3.9 Если все наследующие классы предоставляют идентичную реализацию виртуальной функции базового класса, она должна быть не виртуальной, а реализовывать поведение наследующих классов.

Правило 3.3.10 Удостоверитесь, что возвращаемый тип переопределенной виртуальной функции совместим с возвращаемым типом виртуальной функции.

Правило 3.3.11 Не переопределяйте и не скрывайте невиртуальные функции наследуемого класса.

Правило 3.3.12 При переопределении и переобъявлении функций, используйте идентичные параметры по умолчанию во всех определениях.

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

Правило 3.3.14 В абстрактном классе определяйте оператор присвоения как «protected».

Правило 3.3.15 Удостоверитесь, что базовые классы, всеобщие для 2-х и больше наследующих классов, являются виртуальными.

Правило 3.3.16 Полиморфные способы в наследующем классе очевидно определяйте виртуальными.

Классы: ООП

Правило 3.4.1 Объявляйте данные класса «private».

Правило 3.4.2 Не возвращайте неконстантные ссылки на члены класса из константных функций.

Правило 3.4.3 Не определяйте способов, которые возвращают неконстантные указатели и ссылки на данные с больше ограниченным доступом, чем сам способ.

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

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

Правило 3.4.6 Наследующие классы обязаны наследовать не больше чем от одного не чистого абстрактного класса.

Рекомендация 3.4.7 Все члены публичного базового класса обязаны оставаться валидными для наследующего.

Классы: перегрузка операторов

Правило 3.5.1 Избегайте перегрузки операторов “,”, “&&” и “||”.

Правило 3.5.2 Неизменно реализуйте перегрузку операторов так, Дабы равнозначные операции оставались равнозначными позже перезагрузки.

Правило 3.5.3 Удостоверитесь, что перегруженные бинарные операторы сберегают ожидаемое поведение.

Правило 3.5.4 Объявляйте перегруженные операторы вне класса, Дабы для них работала конвенция приведения по левому операнду.

Правило 3.5.5 При перегрузке оператора индекса “[]“, реализуйте и константную, и неконстантную версии.

Трудность

Правило 4.1 Функции не обязаны иметь избыточную цикломатическую трудностью по Маккабе (>10).

Правило 4.2 Функции не обязаны иметь излишне огромное число статических путей выполнения (>200).

Правило 4.3 Функции не обязаны иметь огромное число доводов (>6).

Поток управления

Правило 5.1 Всякий блок примитива управления потоком («if», «else», «while», «for», «do», «switch») должен заключаться в скобки, даже если он содержит только одну строку, либо не содержит ничего совсем.

Правило 5.2 В булевских выражениях («if», «for», «while», «do» и первом операнде тернарного оператора “?”) неизменно записывайте равенство и неравенство в очевидном виде.

Правило 5.3 Избегайте условных выражений, которые неизменно имеют один и тот же итог (за исключением платформозависимого кода, когда итог на иной платформе может все-таки быть другим).

Правило 5.4 Всякий непустой блок выражения «switch» должен заканчиваться командой «break».

Правило 5.5 Не модифицируйте переменные контроля цикла «for» в теле цикла.

Правило 5.6 Не модифицируйте переменные контроля цикла «while» и «do» в теле цикла больше чем один раз.

Правило 5.7 Переменная контроля цикла «for» должна сравниваться с константой, а не функцией либо выражением.

Правило 5.8 Не используйте «goto».

Правило 5.9 Всякий завершенный блок, помимо тела «switch» должен иметь одну точку входа и (исключая выход по исключению), одну точку выхода.

Правило 5.10 Все точки выхода функций с не пустым типом возврата обязаны возвращать выражение типа возврата.

Правило 5.11 Определяйте в очевидном виде все допустимые ветви условного оператора.

Правило 5.12 Переменные контроля цикла «for» следует объявлять непринужденно внутри «for», а не применять внешние переменные.

Константы

Правило 6.1 Используйте суффиксы «L», «U», «UL» для констант типа «unsigned», «long», «unsigned long».

Правило 6.2 Используйте суффиксы «F», «L» для констант типа «float», «long double».

Правило 6.3 Следите, Дабы константа определялась значением не выходящим за область определения типа.

Правило 6.4 Используйте ескейп-последовательности экстраординарно эталона ISO C .

Правило 6.5 Не смешивайте литералы обыкновенной строки с литералами строки широких символов.

Рекомендация 6.6 Всеобщии переменные и статические члены следует делать константными (ислючая переменную контроля уникальности синглтона).

Конверсия и приведение

Правило 7.1 Используйте только приведение через «static_cast», «dynamic_cast», «const_cast», «reinterpret_cast» либо очевидное приведение через конструктор целевого типа

Рекомендация 7.2 Минимизируйте число приведений.

Правило 7.3 Избегайте приведений из «volatile» в не «volatile».

Правило 7.4 Избегайте приведений из «const» в не «const».

Правило 7.5 Избегайте приведений ссылок и указателей (за исключением приведения через dynamic_cast при поддержке RTTI).

Правило 7.6 Конвертируйте тип числа с плавающей точкой в целочисленный тип экстраординарно через функции стандартной библиотеки («round», «floor», «ceil» и т. п.)

Правило 7.7 Не приводите указатели к базовым типам.

Правило 7.8 Не допускайте неявного приведения доводов функции при ее вызове.

Объявления и определения: конструкция

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

Рекомендация 8.1.2 За исключением объявлений и определений неименованного пространства имен, все инлайн-функции, имеющие внешнюю компоновку и определенные в некотором (включая глобальное) пространство имен, обязаны быть определены в заголовочных файлах.

Рекомендация 8.1.3 За исключением объявлений и определений неименованного пространства имен, все шаблонные определения, имеющие внешнюю компоновку и определенные в некотором (включая глобальное) пространство имен, обязаны быть определены в заголовочных файлах.

Объявления и определения: видимость

Правило 8.2.1 Не затеняйте объявления в внутренних областях видимости.

Правило 8.2.2 Избегайте применения глобальных переменных.

Рекомендация 8.2.3 Используйте декларации «using», либо обозначайте пространство имен очевидно, избегайте директив «using».

Рекомендация 8.2.4 Директивы «using» допускается применять только в основном начальном файле и только позже всех директив «include».

Объявления и определения: языковые ограничения

Правило 8.3.1 Избегайте объявления «static» объектов внутри пространства имен.

Рекомендация 8.3.2 Избегайте излишнего применения «extern» там, где компоновка и так неявно объявлена внешней.

Правило 8.3.3 Избегайте применения «auto» и «register».

Правило 8.3.4 Все идентификаторы обязаны быть уникальны.

Правило 8.3.5 Избегайте неоднозначной грамматики декларации и приведений с поддержкой функций.

Объявления и определения: всеобщие правила

Правило 8.4.1 Не используйте пары символов «l» (буква «эль») и «1» (один), а также «O» (буква «о») и «0» (нуль) в одном идентификаторе.

Правило 8.4.2 Объявляете всякую переменную в отдельной строке отдельным объявлением. Если объявление не самоочевидно, добавляйте соответствующий комментарий.

Правило 8.4.3 Инициализируйте всякий объект при определении. Никогда не используйте объект до первого присвоения ему значения.

Правило 8.4.4 Определяйте переменные как дозволено ближе к контексту применения.

Правило 8.4.5 Не используйте тип «char» при объявлении объектов, участвующих в численных операциях. Используйте очевидное определение знаковости типа: «signed char», «unsigned char».

Рекомендация 8.4.6 Используйте типы классов либо определения типов через «typedef» для обособления типа числа.

Правило 8.4.7 Объявляйте только одно имя в всяком «typedef».

Правило 8.4.8 Не определяйте типы массивов через «typedef».

Правило 8.4.9 Не используйте агрегатные типы без проверки переполнения (массивы языка Си).

Правило 8.4.10 Не используйте указатели на члены.

Правило 8.4.11 Используйте «const» всюду, где это допустимо.

Рекомендация 8.4.12 Присоединяйте “*” и “&” к типу (а не к имени переменных) в объявлениях и определениях.

Рекомендация 8.4.13 Выбирайте знаковые типы беззнаковым.

Исключения

Правило 9.1 Не генерируйте исключения из деструкторов.

Правило 9.2 Генерируйте исключения только объектного типа (от std::exception).

Правило 9.3 Обрабатывайте исключения по ссылке.

Рекомендация 9.4 Используйте механизм обработки исключений С только для регулирования внештатных обстановок.

Рекомендация 9.5 Всякое приложение должно гарантировать освобождение всех источников (исключая локальные объекты) при генерации исключения.

Рекомендация 9.6 Всякое приложение должно гарантировать освобождение всех не механически освобождаемых источников при непредвиденном заключении программы.

Выражения

Правило 10.1 Используйте символические имена взамен определенных значений в коде. Избегайте «magic numbers» (за исключением “”, 0, 1, true, false и однократных строковых литералов).

Правило 10.2 Доступ к массиву должен видимо выполняться в рамках его границ.

Правило 10.3 Не полагайтесь на определенный порядок вычисления операндов выражения.

Правило 10.4 Используйте скобки добавочно для раскрытия сути выражения.

Правило 10.5 Неизменно игнорируйте итог оператора присвоения.

Рекомендация 10.6 При сопоставлении переменной и константы неизменно размещайте константу слева.

Рекомендация 10.7 Избегайте выражений, которые зависят от неявной конверсии операндов.

Правило 10.8 Выражения, используемые в заявлениях («assert»), обязаны быть свободны от сторонних результатов.

Правило 10.9 Не допускайте сторонних результатов в правой части операторов “&&”, “||”, а также в операндах «sizeof» и «typeid».

Правило 10.10 Избегайте инструкций без сторонних результатов.

Правило 10.11 Не используйте следующие операторы со знаковыми операндами: “<<”, “>>”, “&”, “|”, “^”.

Правило 10.12 Валидируйте доводы операторов сдвига.

Правило 10.13 Не используйте знаковые и беззнаковые типы в одном выражении.

Правило 10.14 Не используйте типы с различной арифметической точностью в одном выражении.

Правило 10.15 Не полагайтесь на точные значения чисел с плавающей точкой.

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

Правило 10.17 Проверяйте на нуль операнды делителей при делении и взятии остатка.

Рекомендация 10.18 Проверяйте на неотрицательность операнды целочисленного деления.

Правило 10.19 Избегайте оператора запятой.

Правило 10.20 Избегайте тернарного оператора в выражениях.

Правило 10.21 Используйте унарный минус только со знаковыми операндами.

Функции

Правило 11.1 Все одноименные функции обязаны иметь идентичное поведение, различаясь только числом и типом доводов.

Правило 11.2 Закрывайте все функции не члены, которые не являются частью внешнего инетрфейса в неименованном пространстве имен, в начальных файлах.

Правило 11.3 Обозначайте имя доводов функции как при декларации, так и при имплементации (за исключением имен переменных, которые в имплементации не применяются). Используйте идентичные имена в обоих случаях.

Правило 11.4 Выбирайте передачу по ссылке передаче по значению и по указателю.

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

Правило 11.6 Не используйте многоточия в списке доводов функции.

Правило 11.7 Функция не должна возвращать указатель на механически аллоцируемую переменную, объявленную в теле функции. Взамен этого следует воротить копию объекта.

Правило 11.8 Объявляйте как inline только банальные функции.

Правило 11.9 Не допускайте перегрузки функции для численного типа и для указателя единовременно.

Управление памятью

Правило 12.1 Не задавайте значения по умолчанию для доводов перегруженных функций.

Правило 12.2 Аллоцируйте объекты в памяти с поддержкой «new» и деаллоцируйте с поддержкой «delete». Не используйте функции управления памятью языка Си: «malloc», «realloc», «free».

Правило 12.3 Соблюдайте соответствие «new» — «delete» и «new[]» — «delete[]».

Правило 12.4 При удалении массива объектов указывать число элементов не следует.

Правило 12.5 Не возвращайте разыменованный указатель, если он инициализирован динамически в теле функции.

Правило 12.6 При переопределении «new», неизменно переопределяйте «delete».

Правило 12.7 Операторы «new» и «delete» стоит переопределять статическими очевидно.

Правило 12.8 Позже деаллокации объекта через «delete» неизменно устанавливайте указатель нулевым.

Переносимость

Рекомендация 13.1 Избегайте нестандартизированного поведения.

Рекомендация 13.2 Выбирайте типовые средства языка и стандартной библиотеки дополнительной функциональности предоставляемой операционной системой либо окружением.

Правило 13.3 Не превышайте ограничения транслятора, установленные эталоном ISO C .

Правило 13.4 Не используйте растяжения компилятора либо препроцессора.

Правило 13.5 Избегайте встроенного ассемблерного кода.

Правило 13.6 Не полагайтесь на конструкцию внутреннего представления объектов и переменных.

Правило 13.7 Не приводите указатель на переменную фундаментального типа к указателю на переменную фундаментального типа с больше суровым выравниванием.

Препроцессор

Правило 14.1 Используйте комментарии языка С “// …”, избегайте комментариев в жанре Си “/*… */”.

Рекомендация 14.2 Не используйте табуляцию в начальных файлах.

Рекомендация 14.3 Записывайте директивы препроцессора с началастроки без пробелов между “#” и собственно директивой.

Рекомендация 14.4 Записывайте вложенные директивы сопроцессора с начала строки, но с пробелами между “#” и вложенной директивой.

Правило 14.5 Управляйте условной компиляцией экстраординарно наличием либо отсутствием определения того либо другого токена (при помощи “#ifdef”, “#ifnded”. Исключение составляют случаи, когда сопоставление с константой неминуемо. Скажем, при компиляции кода компилятором определенной версии).

Правило 14.6 Для определения отличия между компиляцией Си и С используйте идентификатор “__cplusplus”.

Рекомендация 14.7 Избегайте комментариев в теле макроса.

Правило 14.8 Все файлы, содержащие начальный код обязаны заканчиваться пустой строкой (вернее символом новой строки по ISO C 2.1/2).

Правило 14.9 Используйте скобки “<>” для включения заголовочных файлов системных и стандартных библиотек, а кавычки — для всех остальных.

Правило 14.10 Избегайте очевидного указания путей в директивах “#include”.

Правило 14.11 Используйте гарды в заголовочных файлах во избежание их повторного включения.

Правило 14.12 Используйте строчные буквы для имен файлов и ссылок на имена файлов (как в директивах include).

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

Правило 14.14 Заключайте в скобки как доводы, так и тело макроса (за исключением односложных тел).

Правило 14.15 Не используйте макросы препроцессора для определения секций кода.

Правило 14.16 Избегайте применения макроса NULL.

Правило 14.17 Используйте константные объекты либо перечисления для определения констант, не “#define”.

Правило 14.18 Не используйте диграфы и триграфы.

Правило 14.19 Не используйте макросы для определения функций, используйте инлайн-функции.

Конструкции, объединения, перечисления

Правило 15.1 Избегайте применения вариативных конструкций (объединений).

Правило 15.2 Не определяйте функции-члены и не используйте модификаторы доступа в конструкциях.

Правило 15.3 Не полагайтесь на численное значение переменной перечисления

Правило 15.4 Избегайте приведения целочисленного типа к перечислению: итог непредсказуем, если значение переменной не входит в область определения перечисления.

Темплейты

Правило 16.1 Избегайте неявного приведения темплейтных классов к самостоятельным типам.

Правило 16.2 Избегайте допустимо конфликтующих способов в темплейтных классах.

Правило 16.3 Инстанцируйте темплейты экстраординарно с доводами темплейта, которые удовлетворяют требованиям интерфейса.

Рекомендация 16.4 Прибегайте к темплейтам только тогда, когда поведение класса либо функции всецело не зависит от типа объекта темплейтного довода.

STL

Правило 17.1 Используйте типовые заголовочные файлы С , определенные эталоном языка, а не устаревшие в растяжением “.h” (“”, не “<sdtio.h>”).

Правило 17.2 Выбирайте контейнеры и алгорифмы STL самодельным аналогам.

Правило 17.3 Для объектов, предуготовленных для применения в контейнерах, копирование должно быть реализовано с максимальной результативностью.

Правило 17.4 Если копирование объекта ресурсоемкое, используйте контейнер указателей либо смарт-поинтеров.

Правило 17.5 Не вставляйте объект наследованного класса в контейнер объектов базового класса (такое работает только с контейнером указателей).

Рекомендация 17.6 Используйте «empty» взамен проверки «size» на 0.

Рекомендация 17.7 Не используйте контейнеры STL в роли публичных базовых классов.

Правило 17.8 Никогда не создавайте контейнеров типа auto_ptr.

Правило 17.9 Используйте строки и вектора взамен динамически аллоцируемых массивов.

Рекомендация 17.10 При вероятности преаллоцируйте контейнер («reserve») предварительно, Дабы избежать повторных реаллокаций в последующем.

Правило 17.11 При передаче векторов функциям языка Си, используйте конструкцию “&v[0]“.

Правило 17.12 Для применения строки STL в виде «char*» с устаревшими функциями используйте экстраординарно «c_str()».

Правило 17.13 Избегайте векторов типа «bool».

Правило 17.14 Предикаты отношения обязаны возвращать «false» для равнозначных значений.

Правило 17.15 Никогда не модифицируйте ключевую часть элемента множества типа «set» либо «multiset».

Рекомендация 17.16 Избегайте смешения типов итераторов.

Правило 17.17 Итог предиката должен зависеть экстраординарно от его параметров.

Правило 17.18 Выбирайте алгорифмы STL собственным циклам.

Правило 17.19 Выбирайте функции-члены контейнеров одноименным обобщенным алгорифмам.

Правило 17.20 Включайте только нужные заголовочные файлы STL.

Рекомендация 17.21 Избегайте применения auto_ptr.

Список литературы

[Stroustrup, 2000] Bjarne Stroustrup: The C Programming Language. Addison-Wesley. 2000

[C Standard, 1999] International Standard ISO/IEC 14882:1998(E) Programming Language C .

[Effective C , 1996] Scott Meyers: Effective C . Addison-Wesley. 1996

[More Effective C , 1996] Scott Meyers: More Effective C . Addison-Wesley. 1996

[Effective STL, 2001] Scott Meyers: Effective STL. Addison-Wesley. 2001

[Industrial Strength C , 1997] Mats Henricson, Erik Nyquist, Ellemtel Utvecklings AB: Industrial Strength C . Prentice Hall. 1997

[Exceptional C , 2000] Herb Sutter: Exceptional C . Addison-Wesley. 2000

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB