На главную Наши проекты:
Журнал   ·   Discuz!ML   ·   Wiki   ·   DRKB   ·   Помощь проекту
ПРАВИЛА FAQ Помощь Участники Календарь Избранное RSS
msm.ru
Модераторы: ANDLL, ALXR
Страницы: (12) « Первая ... 8 9 [10] 11 12  все  ( Перейти к последнему сообщению )  
> #define ИЛИ template? , C++
   
#define ИЛИ template
Гости не могут просматривать результаты голосования.
Гости не могут голосовать 
    Цитата Qraizer @
    Сейчас, увы, Wolfenstein II ждёт, но попозже я накатаю кратенюсенький ликбез.
    Начал тут обдумывать, что писать, и понял, что кратенюсенько не получится. Ладно, тогда пока просто перепишу первый пример на SEH.
    ExpandedWrap disabled
      int copyFile(const char* src, const char* dst)
      {
        void *buf = NULL;
        FILE *inF = NULL;
        FILE *ouF = NULL;
        size_t readed, written;
        int    res = 0;
       
        __try
        {
          buf = malloc(BUF_SIZE);
          inF = fopen(src, "rb");
          ouF = fopen(dst, "wb");
       
          if (buf == NULL) __leave;
          if (inF == NULL) __leave;
          if (ouF == NULL) __leave;
       
          readed = fread(buf, 1, BUF_SIZE, inF);
          while (!feof(inF) || readed != 0)
          {
            written = fwrite(buf, 1, readed, ouF);
            if (written != readed) __leave;
            readed = fread(buf, 1, BUF_SIZE, inF);
          }
          res = 1;
        }
        __finally
        {
          if (ouF != NULL) fclose(ouF);
          if (inF != NULL) fclose(inF);
          if (buf != NULL) free(buf);
        }
        return res;
      }
    Думаю, тут и без ликбеза всё понятно. SEH штука классная. Её отсутствие в POSIX делает мне программинг в нём некомфортным.
      Ну поехали. Напомню, как выглядит C++EH.
      Есть некий блок try, код, исполняемый внутри которого, находится под пристальным наблюдением. Ежели чё, оператор throw может бросить исключение, которое немедленно этим самым пристальным взором обнаружится, и он начнёт поиск подходящего его обработчика. Таковым будет какой-нибудь блок catch, каковые должны располагаться сразу за соответствующими try, и их может быть и больше одного за каждым. Отличаются они своим как бы "параметром": типом исключения, обрабатывать которое этот catch намерен.
      Т.к. try могут быть вложенными, то поиск подходящего catch может быть непростым занятием. Пристальное око сначала просматривает список catch самого внутреннего try. Если там ничего подходящего нет, то следующего try, непосредственно предшествующего только что просмотренному, итп. Ежели ничего найдено не будет, то ой, а если будет, то ура, этот catch и получит и управление, и брошенный throw объект исключения. Подходящесть определяется сугубо типом объекта. Ну, там есть оговорки касательно ссылочности, const/volatile и базовых классов брошенных объектов, ловимых по ссылкам или указателям, но это уже детали. Главное, что селектором catchей выступает именно тип исключения, а значение, удерживаемое объектом, C++EH до лампочки, оно может использоваться программером по своему усмотрению, нести какую-нибудь доп. инфу о возникшей ситуации, например.
      Когда catch выделен и одобрен, око откатывает всё, исполненное от входа в try, к которому одобренный catch присобачен. Ну как откатывает... просто снимает со стека все автоматические объекты посредством вызова их деструкторов и удаляет любые стековые кадры вызванных и не успевших завершиться функций. При этом, т.к. сам объект исключения тоже является автоматическим объектом, но его-то как раз надо сохранить, иначе что же тогда передавать в catch-то, оно аккуратненько выводит этот объект из его области видимости в вносит в область видимости catch. Обычно посредством конструктора копии, что создаёт новый объект, а созданный throw благополучно почивает вместе со своими собратьями.

      Добавлено
      Теперь SEH. В-главных, в отличие от C++EH, который является языковым механизмом, SEH является механизмом операционной системы. Это делает SEH универсальным средством, позволяющим писать приложения на любых языках, писать отдельные их модули на разных языках, встраивать в охраняемые оком блоки сами функции ОС итп. Конечно, при условии, что используемые языковые средства поддерживают SEH, что до недавнего времени для GNUсных инструментов не выполнялось, поэтому писанные на них приложения страдали небольшими утечками и некоторой нестабильностью, исключить которые программеры в принципе-то могли, но сильно заморочившись, поэтому обычно забивали, чай не реакторами управляют.
      А в-остальных, SEH не так уж сильно архитектурно отличается от C++EH. С пристальным взором всё так же, только блок называется не try, а __try. А вот с обработчиками всё сложнее. Точнее, проще. Ну, для нас сложнее, а проще для ока. Исключения (если только они не аппаратные; впрочем, с аппаратными исключениями в C++EH всё ещё печальнее) бросаются API-функцией RaiseException(), которой передаётся тип исключения и его параметры. Причём тип исключения – это нифига не тип, это тупо целое значение. За __try может находиться только один обработчик под названием __except, и его параметром является тоже не тип, а значение. Точнее значение выражения. Ещё точнее – это даже не параметр, а выражение-фильтр, возвращаемое значение которого как раз и говорит оку, а чё собственно-то тому делать, а вызывает его именно око, а __except, чтобы решить, а что собственно возвращать, может заюзать GetExceptionCode() и GetExceptionInformation(), которые ему дадут и тип исключения, и параметры, и даже аппаратный контекст в точке броска исключения, что совсем полезно при аппаратных исключениях. Вот проанализировав всю эту фигню или какую-нибудь фиговую его часть, __except-выражение-фильтр и должно решить, что же ответить оку.
      Дело в том, что око само не знает, __except какого __try вызывать, и это должны решить сами __except. Вот оно и вызывает выражение каждого и смотрит, что ему ответят. Вызывает, естественно, в порядке от самого внутреннего. Если очередной __except вдруг вернёт EXCEPTION_CONTINUE_EXECUTION, это вполне удовлетворит око, и оно просто забудет об исключении, выполнив штатный возврат из RaiseException(). Если __except вернёт EXCEPTION_CONTINUE_SEARCH, то это является ответом оку, что этот __except не тот, который хочет иметь дело с этим исключением, и тому надо спросить следующего. А вот если ответом будет EXCEPTION_EXECUTE_HANDLER, то вот это вот как раз то, что око собственно-то и ждёт и с радостью примет этот __except в качестве целевого.
      Теперь ему остаётся лишь откатить всё взад. А вот как именно, это вопрос гораздо интереснее. SEH-то работает на уровне ОС и ничего не знает о языковых заморочках исполняемого приложения. Вдруг оно вообще на Форте писано, какие там нахрен деструкторы-то.
      Сообщение отредактировано: Qraizer -
        Вот тут-то на арену и выходят те самые __finally. Эти блоки тоже должны располагаться следом за __try. Но не вместе с __except, они с ними взаимоисключающи. У них нет параметров, и всё их назначение заключается в том, чтобы только лишь корректно откатить соответствующие им __try. Что там полезного делать? Ну, обычно это как раз очистка, т.б. освобождение занятых в этом __try ресурсов. Собственно больше там делать нечему. Причём __finally выполняются всегда, даже если __try просто завершается, самым что ни на есть штатным образом. На всякий случай есть AbnormalTermination(), что позволяет __finally выяснить, как именно __try закончился, нормально чи абнормально, но обычно __finally это до лампочки.
        Естественно, при поиске подходящего __except эти __finally игнорятся, их время ещё не пришло, но вот теперь, выяснив, до какого __except ему нужно откатываться, око повторно проходит стек __tryёв вплоть до отобранного __except-ом, только теперь уже игнорит __exceptы, сосредоточившись на __finally и вызывая их. Внимание вопрос: а как же отрабатывают эти __finally, если око не было задействовано? Та не вопрос. Компилер же не дурак, что ему стоит самому в конце __try вызывать __finally, прикинувшись оком, а потом прыгнуть за его тело. Так что в отсутствие исключений оверхед минимальный.
          Цитата KILLER @
          Мне сложно парировать не зная сути задачи. Извини, но все тузы в данном случае у тебя на руках, а я играю в слепую.

          Нормально слился :lool: Какие тузы, о чём ты? Что все эти циклы используют одни и те же переменные, я сказал сразу, так что это не изменение условий на лету. Что в этой ситуации локальный cleanup для каждого build не особо-то помогает, должно быть очевидно даже тебе, если бы ты умел хотя-бы минимально осмысливать написанное. Или туз - моё знание задачи? Ну задача - построить дерево датасетов со всеми требуемыми инвариантами по внешним данным, которые могут прийти кривыми - тебе стало от этого легче? :D Очевидно же, что необходимость переходить к очистке из разных мест от копипаста ТЗ никуда не денется.
            Тут внимательный читатель уже должен просто вопить "чушь! брехня! фигня! если я сделаю return или какой-нибудь break или не дай боже longjmp(), всё рууухнееет!" и будет неправ. Компилятор, поддерживающий SEH, должен корректно обходить сии грабли. Увидел return, значит должен навызывать затронутые им __finally, увидел – ужас – goto, никуда не денется, тоже должен. Итп. Благо эти штуки локальны в функциях, поэтому ему совсем не сложно всё оформить в лучшем виде. Но самый внимательный читатель на этом конечно не успокоится, и на этот раз уже будет прав: ежели в цепочку SEH внедрены модули на разных языках и даже вызовы API функций ОС, что тут может решить компилятор? Правильно, ничего. А он и не решает межфункциональные проблемы. Око – оно ведь не компилятором единым. Но вот что он однозначно может решить сам и решает – так это внутрифунциональные проблемы. Ну как сам решает... почти сам.
            Если без деталей, то общий принцип таков. To be continued, пойду чайник поставлю.
            Сообщение отредактировано: Qraizer -
              Если функция такова, что требует специального подхода к снятию её со стека при откате, компилятор где-нибудь в секции данных создаёт для неё специальную структурку с указанием как минимум количества __try и записями для каждого из них, включающими тип следующего за ним обработчика, __except или __finally, и указатели на точки входа в выражения-фильтры и в сами блоки обработки. Сами эти компоненты он компилит как функции, чтобы око могло их вызывать и получать управление назад. В прологе этой функции компилятор создаёт на стеке ещё одну маленькую структурку, т.н. SEH-кадр, в которую пишет ссылку на эту вот структурку, специально для этой функции подготовленную, и на функцию локального ока, которая будет при откате этой функции заниматься разбором полётов и разгребать эти __try. Обычно это всегда одна и та же некая LocalUnwind(), которая входит в состав RTL, но если писать на асме, то мы вольны тут делать, что угодно, лишь бы в соответствии с правилами SDK. Конечно, симметрично в эпилоге этот SEH-кадр со стека изымается. Оверхед невелик, несколько инструкций в прологе и эпилоге, но в размере секции данных оверхед может быть и поболе, чем невелик, да.
              Это ещё не всё. В структурке есть спец.поле, которое помечает индекс текущего __try. Ну или не индекс, а поинтер. Не суть, лишь бы ему самому не запутаться было. При входе в __try компилятор помечает сие инкрементом индекса или как он там оформляет свои структурки, при выходе наоборот. Оверхед тоже весьма крохотный. Так что при исполнении LocalUnwind() всегда знает, где что в этой функции конкретно счас, что и докуда исполнилось, где искать записи об __except и __finally итп. И если ей сказали, мол, давай-ка поищи мне самый-самый __except(), а потом сказали а давай-ка следующий, а в следующий раз а дай-ка теперь __finally, а давай ещё, и ещё один, а она такая ой, всё, больше нету, то они с ОСью друг друга прекрасно поймут, при этом тонкости нагенеренных структурок самой ОСи до фени, это забота LocalUnwind(). Вообще говоря, эта самая LocalUnwind() задействуется компилятором и при всяких там break/return итп, т.к. это проще, чем генерить код, а сама LocalUnwind() вообще довольно-таки проста, т.к. итерироваться по записям и вызывать код по поинтерам несложно, а тут так вообще только __finally в известном диапазоне поискать да повызывать. Но за все компиляторы говорить не буду. Тем не менее, некий оверхед-таки есть, и чтобы максимально от него избавиться, следует устранить избыточные вызовы LocalUnwind(). Вот MS покумекала и спецом для этого ввела ещё __leave, который тупо прыгает на конец текущего __try, так что никакой размотки стека, даже локальной, становится не надо.
              Но и это ещё не всё. Одну конкретно взятую функцию LocalUnwind()-то обработает, но что делать с несколькими вызванными и незавершившимися функциями, особенно если половина из них лежит в DLL, писанных на Дельфи или в COM-объекте на VB? Вот тут-то на сцену выходит великая и могучая GlobalUnwind(). От неё зависит итерация по стеку в поиске следующего SEH-кадра и вызова LocalUnwind() для него, чтобы та нашла очередной __except и запросила его фильтр. Которой может оказаться совсем другая LocalUnwind(), Дельфёвая, например. А то и ОСовая. На самом деле ей не так уж и надо быть великой и могучей. Пока. Всего-то найти следующий кадр и джампнуться на его хендлер. Ну ещё мелочи типа передачи ему некой внутренней инфы, чтобы она потом на втором проходе по стеку обратно вернулась. А ещё она должна, если найдёт подходящий __except, зафиксировать найденную в коде точку отката, определить границы подсписка затрагиваемых структурок и вызвать на этот раз API-функцию RtlUnwind().
              И вот она уж если не великая и могучая, то по крайней мере так выглядит. Она выполняет собственно размотку стека и откат выполнения, последовательно вызывая GlobalUnwind() для всех SEH-кадров в указанных границах, которая вызывает LocalUnwind(), которая вызывает __finally... а в конце отката – указанный блок __except. Естественно при этом стек чистится от всех служебных вызовов, начиная с RaiseException(), ибо они снимаются с выполнения одними из первых.

              Добавлено
              В результате на уровне ОС мы имеем единую архитектурную базу для обработки исключений, независящую ни от языка, ни от взаимодействия компонентов и модулей приложения. Это круто. К примеру, ты можешь вызвать DLL на Билдере, та вызовет EnumWindows(), указав коллбэком свою функцию, из неё вызовется Дельфёвый компонент, который вызовет EnumChildWindow(), а её коллбэк на вызове эдак 8-ом вдруг бац! и бросит исключение. Которое не только нормально перехватится у тебя, отмотав всё в точку вплоть до вызова Билдера, но по дороге ещё и все подчистится, включая внутренние временные ресурсы самих ОСовых EnumWindows() и EnumChildWindow(), и временные объекты Дельфей и Билдера.
              К слову о птичках. Думаю, уже не надо объяснять, почему C++EH просто обязан быть основан на SEH. Потому что это единый механизм, и функционировать он должен как единое целое. Именно тот факт, что только недавно GNUсные компиляторы начали учитывать SEH, а до этого они знать о нём ничего не хотели и тупо юзали какой-нибудь longjmp() для catchей, приводил к тому, что и ресурсы текли, и стабильность страдала, ибо нормально не выполнялся откат ни ОСовых функций, ни DLLных, задействовавших SEH. Сейчас такая поддержка вроде есть, но только для внутренних целей библиотек поддержки C++EH. Расширений языка для поддержки SEH в своих программах ты так и не получишь.

              Добавлено
              И в заключение. C++EH реализовать свои плюшки на ядре SEH уже несложно. Всего-то: транслируем каждый try во вложенные __try, каждому назначаем свой __except, в который транслируем соответствующий catch; в качестве выражений-фильтров указываем обобщённую RTL-функцию, анализирующую запись RTTI брошенного объекта. Каждый автоматический объект создаём под собственным __try, в __finally которого помещаем вызов его деструктора. Транслируем throw в RaiseException() с передачей кода исключения, зарезервированного для C++EH, и парой параметров: указатель на созданный объект исключения и на его RTTI-запись. Всё. Ну, почти. Всё-таки блоков как-то дохрена много получается, поэтому для экономии __tryёв там используются немного другие, более ёмкие структурки и как следствие немного более другие LocalUnwind() и GlobalUnwind(). Особенно последняя, которая тут гораздо более напоминает великую и могучую, т.к. ей, помимо того, что уметь кастовать производные классы в базовые, а также передавать объект исключения по значению, ежели вдруг, ещё надо объект исключения перемещать из одной области видимости в другую и озаботиться его разрушением по выходу из catch. И всё это только на основе динамической информации из RTTI-записей, ибо она скомпилена давным-давно и лежит себе готовая к употреблению в RTL языка, и какие там исключения нам вздумается бросать на этот раз, она заранее знать ну никак не может. А ещё и выражения-фильтры должны не тупо RTTI на равенство сравнивать, а учитывать нюансы иерархий классов и доступность базовых подобъектов, ибо завещал Отец-Основатель, что каст к непубличному базовому суть грех величайший. Собственно из-за этого C++EH и SEH-кадры отличаются, и при их совмещении в программе возникают сложности. Но они легко преодолимы.
              Сообщение отредактировано: Qraizer -
                По-моему надо создать на форуме тему "ссылки на интересные ликбезы от Qraizer" :)
                  Цитата OpenGL @
                  Нормально слился :lool: Какие тузы, о чём ты?

                  Ты перечитай что ты пишешь. Ты привел пример. Я тебе его разбил, ты начал говорить - тут алгоритм неделимый, а тут мне возвращаются не указхатели, а тут еще какая то шняга. И что мне каждый раз на твои глупые ограничения придумывать новый код?
                    Цитата KILLER @
                    Я тебе его разбил, ты начал говорить - тут алгоритм неделимый, а тут мне возвращаются не указхатели, а тут еще какая то шняга.

                    И? :rolleyes: Он действительно неделимый, а что в цикле заполняется сразу несколько данных, нужных далее - по сути уже не так уж и важно. А разбить ты можешь хоть код, хоть свою голову о стенку - реализацию понятней, чем в лоб с goto, ты не напишешь :D

                    Цитата KILLER @
                    И что мне каждый раз когда укажут на то, что я опять не понял условие задачи придумывать новый код?

                    fixed :D
                    Сообщение отредактировано: OpenGL -
                      Qraizer, не очень понял, зачем ты это тут написал :) Описано хорошо и интересно :good:
                      Но вполне может потеряться в теме.
                        Qraizer, а оформи-ка ты это лучше в C/C++ FAQ :) Если добавишь немного кодом, будет совсем хорошо.
                          Цитата OpenGL @
                          И? :rolleyes: Он действительно неделимый, а что в цикле заполняется сразу несколько данных, нужных далее - по сути уже не так уж и важно. А разбить ты можешь хоть код, хоть свою голову о стенку - реализацию понятней, чем в лоб с goto, ты не напишешь :D

                          Что И?
                          Ты уже реально похоже разбил свою голову об стенку, раз не понимаешь что тебе пишут. Я тебе пишу - я не знаю деталей задачи вообще. Я не знаю что там за алгоритм. Я не знаю по сути ни-хре-на. У меня есть приведенный тобою псевдокод.
                          Я его разбил - ты начал писать что говно. И тут же начал писать уточнения какие то. Извини - но я не телепат, чтоб знать что у тебя там за алгоритм, какие у тебя там структуры данных, что там со всем этим происходит, и что вообще ты там делаешь. Соответственно за неимением информации - я, собственно как и любой другой человек, не в состоянии тебе что то обосновать. Именно это я тебе и написал. Но и это тебя не устроило.

                          Ну иди бей свою голову об стену. Спор превратился в какой то голимый троллинг. По этому я из него выхожу. Интерес к дисскуссии пропал. Я лишь сделал вывод что на словах ты Лев Толстой, а на деле ниразу goto не юзал. Но если вот если БЫ, да каБЫ ты писал на Си, то обязательно бы юзал его на право и на лево. Ну и флаг тебе в руки. Юзай что хочешь. Мне по сути вообще плевать.
                          Тем более что у мня появились немного другие задачи, из за которых я не собираюсь отвлекаться на этот троллинг. Тролльте дальше без меня. Можешь считать что я тупо слился и мне тебе нечего противопоставить. Ну что поделаешь, вот такой я нуб. Так и не понял весь смысл юзанья goto.

                          Добавлено
                          Цитата OpenGL @
                          что я опять не понял условие задачи

                          :lol: :lol: :lol: :lol:
                          Покажи где ты привел условие задачи? Ты реально об стену долбанулся чтоли ? Или тот псеводокд твой - и есть условие задачи может быть? LooooL сцуко, до слез. Чтоб тебе такие условия задачи ставили.

                          Добавлено
                          Цитата Qraizer @
                          Заюзал бы я сейчас в подобной ситуации goto? Когда код с ним написан за пять минут, не нуждается в отладке, прост, понятен и производителен? Обязательно.

                          У меня немного другой склад ума значит. Не пропитанный блоксхемами. Поэтому мне бы в голову даже не пришло юзать там goto. Это уже в готовый код - врубиться и понять что там происходит и переписать без goto - сложно. А если нет готового кода, я бы даже не думал о goto. Вот такой у меня подход.
                          Мозг человека так устроен, что если ты что то не используешь, то это просто уходит в далекие недра мозга. Именно по этому я бы писал по другому, без goto. Если бы я частенько юзал goto, или он бы везде мелькал напоминая о себе - возможно тогда, я бы и задумался его юзнуть. А когда он выпилен из жизни, то я как то не задумываюсь о нем вобще. До этой темы - например он ушел на такой задний план, что при программировании, даже когда он мог бы облегчить жизнь - я бы о нем даже не вспомнил.
                          Сообщение отредактировано: KILLER -
                            Цитата KILLER @
                            Покажи где ты привел условие задачи?

                            Вот это:
                            Цитата OpenGL @
                            три больших отдельных цикла, в них идёт построение сложных структур данных (используется несколько локальных переменных), везде нужны проверки, что всё хорошо, и если не всё - все построенные структуры надо удалить.

                            и, возможно, псевдокод этого из следующего сообщения вполне себе этим условием является - всё, что не входит в это описание, для задачи "показать, как это написать без goto с сохранением читаемости" совершенно не нужно.

                            Цитата KILLER @
                            До этой темы - например он ушел на такой задний план, что при программировании, даже когда он мог бы облегчить жизнь - я бы о нем даже не вспомнил.

                            Хм. Открываем первую страницу, вводим в поиске goto, и ВНЕЗАПНО видим, что первым его упомянул ты, причём трижды в одном сообщении. Круто ушёл он у тебя, аднака :crazy:
                            Сообщение отредактировано: OpenGL -
                              Цитата OpenGL @
                              Цитата KILLER @
                              Покажи где ты привел условие задачи?

                              Вот это:
                              Цитата OpenGL @
                              три больших отдельных цикла, в них идёт построение сложных структур данных (используется несколько локальных переменных), везде нужны проверки, что всё хорошо, и если не всё - все построенные структуры надо удалить.

                              и, возможно, псевдокод этого из следующего сообщения вполне себе этим условием является

                              Ну вообще это уже описание некоторого решения, а не самой задачи.
                                Цитата OpenGL @
                                Вот это:

                                Вот это по твоему условие задачи? Лол. Тебе на работе такие же условия ставят для разработки? :lol: :lol: :lol:
                                Ты щас прикалываешься или что? Так я тебе разбил три цикла на три функции, что тебя не устроило? Остальное могу словами объяснить. Аля сложные структуры данных вот там дальше гдето берут и очищаются.

                                Цитата OpenGL @
                                и, возможно, псевдокод этого из следующего сообщения вполне себе этим условием является - всё, что не входит в это описание, для задачи "показать, как это написать без goto с сохранением читаемости" совершенно не нужно.

                                Слушай, твой псевдокод представляет из себя три цикла в одной функции и один клинап. Это ты называешь условием? :D Не смеши людей, еще раз тебе повторяю. Пусть тебе кто то другой переписывает с такими условиями. Я пасс.

                                Цитата OpenGL @
                                Хм. Открываем первую страницу, вводим в поиске goto, и ВНЕЗАПНО видим, что первым его упомянул ты, причём трижды в одном сообщении. Круто ушёл он у тебя, аднака :crazy:

                                В троллинге я могу упоминать все что угодно, это ведь не означает что когда я занимаюсь решением какой либо задачи, я обязательно думаю о goto? Вон у нас в политике сколько тем, значит ли это что все великие форумные политики и думают об этом всегда и всюду?

                                Добавлено
                                Цитата D_KEY @
                                Ну вообще это уже описание некоторого решения, а не самой задачи.

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

                                Добавлено
                                В любом случае, у меня появились вещи по важнее чем обсуждение каких то goto. Для себя лично я выводы сделал.
                                Сообщение отредактировано: KILLER -
                                0 пользователей читают эту тему (0 гостей и 0 скрытых пользователей)
                                0 пользователей:
                                Страницы: (12) « Первая ... 8 9 [10] 11 12  все


                                Рейтинг@Mail.ru
                                [ Script execution time: 0,0642 ]   [ 18 queries used ]   [ Generated: 19.04.24, 12:33 GMT ]