1. C++ / Говнокод #18197

    +906

    1. 01
    2. 02
    3. 03
    4. 04
    5. 05
    6. 06
    7. 07
    8. 08
    9. 09
    10. 10
    11. 11
    12. 12
    13. 13
    14. 14
    15. 15
    16. 16
    17. 17
    18. 18
    19. 19
    20. 20
    21. 21
    22. 22
    23. 23
    24. 24
    25. 25
    26. 26
    class LoaderLock
    	{
    	public:
    		void lock();
    		void unlock();
    		bool IsLocked() const;
    		LoaderLock() = default;
    
    	private:
    		LoaderLock(LoaderLock&) = delete;
    		LoaderLock(LoaderLock&&) = delete;
    		LoaderLock& operator=(LoaderLock&) = delete;
    		LoaderLock& operator=(LoaderLock&&) = delete;
    		bool _Locked = false;
    		ULONG _cookie = 0;
    		std::unique_ptr<void, std::function<void(void*)>> _ntdll{ LoadLibrary("NTDLL.DLL"), [](void* h){if (h)FreeLibrary((HMODULE)h); } };
    		typedef NTSTATUS(__stdcall*LdrLockLoaderLockFunc)(
    			ULONG Flags,
    			ULONG *State,
    			ULONG *Cookie);
    		LdrLockLoaderLockFunc _LdrLockLoaderLock = !_ntdll ? 0 : (LdrLockLoaderLockFunc)GetProcAddress((HMODULE)_ntdll.get(), "LdrLockLoaderLock");
    		typedef NTSTATUS(__stdcall*LdrUnlockLoaderLockFunc)(
    			ULONG Flags,
    			ULONG Cookie);
    		LdrUnlockLoaderLockFunc _LdrUnlockLoaderLock = !_ntdll ? 0 : (LdrUnlockLoaderLockFunc)GetProcAddress((HMODULE)_ntdll.get(), "LdrUnlockLoaderLock");
    	};

    Уже давно минул 2014 год, а C++11 не перестает радовать нас размазанными по интерфейсу конструкторами и деструкторами.

    Запостил: LispGovno, 18 Мая 2015

    Комментарии (124) RSS

    • Наклал, хаккир
      Ответить
    • Кстати, а почему с ntdll никто не линкуется, а вечно ебутся с LoadLibrary() + GetProcAddress()?
      Ответить
      • Нет либ файла с недокументированными апи? не сквернословь
        Ответить
      • всем влом делать импорт либу? Глянул, у меня в Win SDK ее нет, наверно она только в DDK или как там его сейчас зовут.
        Ответить
        • Алсо, список ее функций вполне успешно получается
          http://pastebin.com/fsEZ3Avr
          Ответить
    • >std::unique_ptr<void, std::function<void(void*)>>
      Как хорошо быть Си мастер рейс.
      Ответить
      • > Си мастер рейс.
        Кем и почему? ну и лучше unique_ptr<void, void(*)(void*)>
        Ответить
    • Я не гуру, но это концепт BasicLockable. Да?
      Ответить
    • > LdrLockLoaderLock
      Yo dawg

      Полное API, наверное, выглядит так:
      LdrLockLoaderLock
      LdrUnlockLoaderLock
      LdrLockLoaderUnlock
      LdrUnlockLoaderUnlock
      LdrLockUnloaderLock
      LdrUnlockUnloaderLock
      LdrLockUnloaderUnlock
      LdrUnlockUnloaderUnlock
      Ловить дедлок в такой схеме, наверное, было бы равноценно потеряться в пятимерном пространстве.
      Ответить
      • UnldrUnlockUnloaderUnlock... Ты половину функций пропустил.
        Ответить
    • Это же воробушек с левого бока
      Ответить
    • Больше RAII для бога RAII (не читайте перед сном):
      class Library
      {
      public:
          Library(const char *name) : mod(LoadLibrary(name)) {}
          ~Library() { FreeLibrary(mod); }
          template <typename T> T GetProcAddress(const char * name) {
              return ::GetProcAddress(mod, name);
          }
      private:
          HMODULE mod;
      };
      
      class LoaderLock
      {
      public:
          LoaderLock()
          {
              ntdll.GetProcAddress<NTSTATUS (__stdcall *)(ULONG, ULONG*, ULONG*)>("LdrLockLoaderLock")(0, 0, &cookie);
          }
          ~LoaderLock()
          {
              ntdll.GetProcAddress<NTSTATUS (__stdcall *)(ULONG, ULONG*)>("LdrUnlockLoaderLock")(0, &cookie);
          }
      private:
          Library ntdll { "ntdll.dll" };
          ULONG cookie;
      };
      Ответить
      • Я тебя расстрою может, но GetProcAddress вызывает LdrLockLoaderLock и LdrUnlockLoaderLock. И не очень пони зачем Library написал, код выше делает также, только средствами стд
        Ответить
        • > GetProcAddress вызывает LdrLockLoaderLock и LdrUnlockLoaderLock
          А этот лок нереентерабельный?
          Ответить
          • реентерабильный, просто ты три раза его захватил и отпустил подряд вместо того чтобы сделать это один раз
            Ответить
            • Мне похуй, если честно. Я ведь ещё и либу ищу, рефаю и дерефаю на каждый чих (так что есть вероятность, что не 3, а все 5). А раз лок реентерабельный - так оно ещё и работать будет ;)
              Ответить
        • > средствами стд
          И при этом выглядит как ёбаный пиздец, угу. Моё Library по крайней мере хоть какие-то зайчатки инкапсуляции и удобства показывает...
          // код курильщика
          std::unique_ptr<void, std::function<void(void*)>> _ntdll{ LoadLibrary("NTDLL.DLL"), [](void* h){if (h)FreeLibrary((HMODULE)h); } };
          
          // код здорового человека
          Library _ntdll { "ntdll.dll" }
          Ответить
      • Library написал чтобы сделать вот такой пиздец:
        class Library {
            // ...
            template <typename Ret, typename... Args> 
            Ret operator () (const char * name, Args... args) {
                return ((Ret (*)(Args...))GetProcAddress(name))(args...);
            }
        };
        
        class LoaderLock {
        public:
            LoaderLock() { ntdll("LdrLockLoaderLock", 0, 0, &cookie); }
            ~LoaderLock { ntdll("LdrUnlockLoaderLock", 0, &cookie); }
        private:
            Library ntdll { "ntdll.dll" };
        };
        Ответить
        • > Library ntdll { "ntdll.dll" };
          Тебя походу торкнули фигурные скобки
          Ответить
          • DSL для прикручивания апишек:
            Library ntdll { "ntdll.dll" };
            Function<NTSTATUS (__stdcall *)(ULONG, ULONG*, ULONG*)>
                LdrLockLoaderLock { ntdll, "LdrLockLoaderLock" };
            Function<NTSTATUS (__stdcall *)(ULONG, ULONG*)>
                LdrUnlockLoaderLock { ntdll, "LdrUnlockLoaderLock" };
            Ответить
            • Допилить что ли поддержку линупса (dlopen/dlsym) да выложить на гитхаб...
              Ответить
              • Удачи!
                Ответить
              • Совсем заняться нечем?
                Ответить
                • Ну почему. На работе нужна была такая либа одно время, но её не было, поэтому наговнокодили с тайпдефами... А тут в c++11 такая няшнота получается - ни одной лишней строчки.
                  Ответить
                  • Ясно. Пишу тебе из под ведра
                    Ответить
                    • Планшет взял или телефон?
                      Ответить
                      • Телефону
                        Пытаюсь юзерскипты поставить
                        Ответить
                        • А я думал, что BlueStacks.
                          Ответить
                          • пасаны, пора приложение говнокод пилить для ведра
                            Ответить
                            • на 5 XE можно кодить на делфях под андроид.
                              Я даже прокси-чекер накомпелял, но девайся нет, тоска.
                              Ответить
                              • У тебя какой то фетиш на эти чекеры
                                Ответить
                                • Не только.
                                  http://implement.do.am/Images/6545435345.png

                                  Прога должна была увидеть свет пару лет назад. Проект изначально разрабатывался на AutoIt, потом был переписан на PureBasic и наконец на Delphi. Затем я взялся переписывать код на FreePascal, чтобы прогу можно было безбоязненно распространять, но встретил на пути слишком много препятствий.
                                  Ответить
                                  • Антивирус Бабушкина?
                                    Ответить
                                    • Нет, это не фейк. Я приложил максимум усилий, чтобы сделать прогу устойчивой и полезной. Прога отлаживалась с fastmm, и до сих пор работает под этим ММ. Никакой функциональщины, одно слошное ООП.
                                      Ответить
                            • Пили.
                              Ответить
                              • Сессия фактически началась - один не вывезу. Помощь треба
                                Ответить
                                • я б не отказался помочь, но я еще тот распиздяй. Да и нормальной апишки у ГК нету.
                                  Ответить
                            • Прошу добавить туда оффлайн-режим с возможностью поиска по ГК и отображения удалённых постов (не зря ж я их качал). Ну или писать программу так, чтобы потом можно было добавить.
                              Ответить
                              • А ты участвовать в разработке не будешь, пельмень?
                                Чет мне кажется что наш уютненький не поддерживает нормального апи так что придётся парсить хтмл ручками
                                Ответить
                                • > мне кажется
                                  Креститься надо. Само собой не поддерживает... Но, с другой стороны, тут няшный xhtml, который вполне жрётся xml парсерами.
                                  Ответить
                                  • А есть такой, который не жрется?
                                    Ответить
                                    • Простой html не жрётся. Ему специальный парсер нужен.
                                      Ответить
                                      • А, я чет тупанул
                                        В любом случае сейчас у меня предсессия, потоп в конце июня сессия, так что пока запишу в хотели, если не обленюсь буду летом пилить
                                        Ответить
                                        • >потоп в конце июня сессия
                                          Где здесь пропущена запятая?
                                          Ответить
                                      • Я думаю, в данном конкретном случае всё же идеологически важен самописный парсер на регэкспах.
                                        Ответить
                                • Я буду незримо присутствовать где-то рядом. А так мне лень...
                                  Мда. Главное - сделать парсилку потоньше, а то вдруг API добавят.
                                  Ответить
                                  • Один фиг - если заменят все придётся или перепиливать или адаптеры втыкать по канонам ооп
                                    Ответить
                                  • Опи не добавят, тут и так всякие стерторы ботов водят
                                    Ответить
                                    • "Туалет не добавят, тут и без этого всякие бомжи срут."

                                      Имхо, вреда от API не будет - все, кто хотел, уже ботов написали.
                                      Ответить
                            • Дык было вроде.
                              Ответить
                              • Вот это поворот
                                Василий, подробнее
                                Ответить
                                • Семен когда был вменяемым. Постил прикладуху для андроида для чтения ГК. надо на гитхабе поискать sam может всплывет
                                  Ответить
                                  • Так это настоящий s-a--m постил. А потом ныне покойный s-a--m, которого в девичестве звали anonimзабылкакойхеш, украл у него аккаунт.
                                    Ответить
                                    • Логично, но мы делаем вид, что тупые
                                      Ответить
                                    • >настоящий s-a--m
                                      Бля а я то все думал, что это все тот же чел, только после обострения.

                                      ШОК за Семена в ГК срал его злой брат близнец. [u]Смотреть онлайн (Только для владельцев платных аккаунтов)[u]
                                      Ответить
                      • tampermonkey не идет на телефоне, сюда по отзывам - не только у меня
                        Ответить
                        • а на что ты рассчитывал хе хе
                          Ответить
                          • На то, что приложение и гугломаркета запустится и будет делать то, что обещали авторы.
                            Безумие, да?)
                            Ответить
                            • #### Important ###
                              Since this app is more a pilot study than a real product I worked on Tampermonkey for Dolphin browser quite a while and found recently the time to bring it into a beta state. You can get it from here:
                              https://play.google.com/store/apps/details?id=net.tampermonkey.dolphin

                              учитывая, что ему ещё и браузер особенный нужен...
                              ЗАТО БЕСПЛАТНО!
                              Ответить
                              • да этот бы запустился и норм
                                https://play.google.com/store/apps/details?id=net.biniok.tampermonkey


                                может мозилка и грейсманки под ведром смогут?
                                Ответить
                  • > ни одной лишней строчки.

                    потому что ты обработку ошибок забыл.
                    Ответить
                    • А нафига она в декларативном описании? Проверка будет запрятана в Function и Library (кидаем исключение, если не нашли функцию или либа не загрузилась). Либо будет непосредственно перед вызовом if (somelib.somefunc) somelib.somefunc(...).
                      Ответить
                      • > Проверка будет запрятана в Function и Library

                        ну ты как бы сверху и привел часть их реализации. GetProcAddr() без проверки возврата непредсказуемая штука.

                        ЗЫ по моему опыту такой syntax sugar только частично помогает. грабли наступают тогда когда в разных версиях виндов у функций аргументы (и/или их типы) меняются. и версию виндов надо динамичски проверять...
                        Ответить
                        • Ну реализация выше - хуёвая и без проверок, тут я не спорю :)

                          А насчёт разных аргументов можно вот так попробовать (искуственный пример):
                          class foo_lib {
                          public:
                              // false - тот самый required
                              Library foo { "foo.dll", "libfoo.so.1", "libfoo.so.2" };
                              Function<int (int, int), false> foo_v1 { foodll, "foo" };
                              Function<int (double), false> foo_v2 { foodll, "foo" };
                              bool new_foo_version_detected;
                          public:
                              foo_lib() {
                                  new_foo_version_detected = ...;
                              }
                              int foo(int x, int y) {
                                  if (new_foo_version_detected)
                                      return foo_v2(x);
                                  return foo_v1(x, y);
                              }
                          };
                          Ответить
                        • Хотя я вот хочу отказаться от шаблонов, и попробовать наебашить на макросах, чтобы в сишке и старых крестах можно было заюзать...
                          Ответить
                          • > и попробовать наебашиться до макросов
                            Ответить
                            • Ага, один раз я до них уже наебашился (AES на препроцессоре).
                              Ответить
                          • сырой С для прикладухи - в ж.
                            Ответить
                            • Ну либы же не только в прикладнухе надо подгружать.
                              Ответить
                              • в не-прикладухе - системщина, встроенщина, сетевуха - там народ (например я) предпочитает явный стиль работы с системой, и библиотеки только по нужде используются (SOUP).

                                только в прикладухе народ усиленно страдает "не хочу ничего про систему слышать и видеть, лучше еще какую библиотечку качнуть".
                                Ответить
                                • переносимость просто нужна
                                  Ответить
                                  • переносимость с виндов на винды?

                                    либа решает виндово-специфические проблемы. на каком линухе класс проблем "недокументированые функции кернела и трахания с их вызовом" просто отсутствует. (все что нужно есть в хидерах, а новые фишки можно вызвать с помощью syscall() макро из libc.)

                                    а если это какой плагиновый интерфейс, то есть более простые способы доступа, нежели чем куча GetProcAddr()/dlsym().
                                    Ответить
                      • А что будешь делать с SetCurrentDirectory, SetCurrentDirectoryA и SetCurrentDirectoryW?
                        Ответить
                        • Оставлю версию с A или с W по ситуации, ибо SetCurrentDirectory не существует.
                          Function<NTSTATUS (__stdcall *)(LPCSTR)>
                              SetCurrentDirectory { ntdll, "SetCurrentDirectoryA" };
                          Ответить
                          • Короче нужно как-то вот так сделать
                            auto SetCurrentDirectory = make_function<
                                BOOL WINAPI (LPCSTR),
                                BOOL WINAPI (LPWCSTR)
                            > 
                            ( ntdll,
                                 "SetCurrentDirectoryA",
                                 "SetCurrentDirectoryW"  
                            );
                            Ответить
                            • А нафиг они тебе одновременно? Половина проги на wstring, а вторая на string?
                              Ответить
                              • Какое то особое извращение
                                Ответить
                                • Да в общем-то для крестопроги ничего особенного...
                                  Ответить
                                  • Этож кресты. Там и кобросвиноконь-дракон - обычное явление
                                    Ответить
                                  • Пс, пацанчек, хочешь погамать?

                                    http://store.steampowered.com/app/332200
                                    Ответить
                              • > А нафиг они тебе одновременно?
                                Перегрузкой оператора() выберется нужная версия SetCurrentDirectory
                                Ответить
                        • как и в официальных хидерах? две инстанции на *A() и на *W(). плюс референс указывающий на одну из них, в зависимости от `UNICODE` (или как там дефайн нынче называется).
                          Ответить
                          • Кресты же. SetCurrentDirectory(char*), SetCurrentDirectory(wchar_t), нужную перегрузку выберет компилятор.
                            Я бы вообще предпочел загрузить только юникодную функцию и перегонять в неё из utf8.
                            Ответить
                    • Мне вот такой вариант нравится - добавить в описание функций флажок required.

                      Если required и не нашлась функция или либа - кидаем исключение сразу.

                      Если не required и не нашлась - кидаем исключение при вызове оператором (). Можно проверить оператором bool(), чтобы понять, есть ли эта функция в данной версии либы.
                      Ответить
                      • и добавить кэширование результата GetProcAddr().
                        Ответить
                        • Надо в конструкторе чтобы уже было известно загрузилась функция или нет. Никаких кеширований

                          А то ведь везде где вызываешь расставлять ловлю исключений на тот случай если не загрузилась функция - та ещё упоротость
                          Ответить
                          • Да не надо расставлять ловлю исключений. Всегда можно посмотреть, загрузилась ли функция (operator bool). А если функции нет, но код этого не учитывает и всё равно дергает operator () - это самая настоящая исключительная ситуация, в которой не грех вбросить исключение (если его тут не бросить - один хуй segfault всё распидорасит.

                            А если флаг required установлен - то исключение вылетит в момент конструирования, где его несложно поймать (или не ловить).

                            Как-то так я себе это представлял ;)
                            Ответить
                            • Да не буду я каждый раз проверять. Нужно в одном месте проверять где конструировал
                              Ответить
                            • http://4.bp.blogspot.com/-8gD74dD_-n0/VR4xpyCCwII/AAAAAAAAA6Q/DN7GzyZVPfE/s1600/HYMkgfnkn5o.jpg
                              Ответить
                            • >> один хуй segfault всё распидорасит

                              Распидорашу, если ещё раз меня так назовёшь.

                              Кстати, почему ты и Тарас так любите меня называть хуем?
                              Ответить
                          • Ну и в случаях, когда надо выбрать функцию в зависимости от версии - делаем враппер как в >>286917 и кидаем исключение из конструктора, если не нашлось никаких кандидатов.
                            Ответить
                  • Есть кандидат в boost - boost.dll. Смотел ее?
                    Ответить
    • Почему уникве_птр инстанциируется двумя параметрами?
      Ответить
      • Второй - функция, которая вызовется для освобождения.
        Ответить
        • Вот я ушел в телефон и на сайте все сразу скисло. Где все? Ау! Где гоатсЕ? Ау!
          Ответить
          • Какой Кегдан )))
            Ответить
          • Какой Кегдан )))
            Ответить
          • Возможно, просто не осталось интересных тем для разговоров.
            Появление комментариев на ГК подобно испарению/кристаллизации. Нужен какой-то центр, вокруг которого начнёт расти кристалл дискуссии. Ну или, если сравнивать с испарением, центр парообразования дискуссии.
            В выходные посетители обычно уходят с работы и не участвуют в обсуждениях, на ГК остаются только школьники, с этим ничего не поделать. А вот если календарь не показывает никаких праздников, надо начинать флудить и троллить, а не просто периодически обновлять сток, ведь все обновляют сток и не пишут комментарии, если им не на что ответить.
            Ответить
            • грусть-тоска-одиночество
              Ответить
              • Можно сесть на окно с телефоном/планшетом, завернуться в плед, кодить на жабе (только главное - не разлить и не обжечься исключениями) и с грустным лицом обновлять сток.
                Ответить
        • Так там не функция в параметре, там сигнатура функции.
          Ответить
          • Там и сигнатура функции в параметре шаблона и сама функция в параметре конструктора. Читай внимательней.

            P.S. Код не taras-safe, слишком длинные строки.
            Ответить
            • А как её вызывать-то надо, если сигнатура - параметр шаблона? Или там на самом деле требуется лишь наличие оператора () с определёнными параметрами, а шаблон нужен лишь чтобы можно было пихать и функции, и лямбды, и std::function?
              Ответить
              • std::unique_ptr<void, std::function<void(void*)>> _ntdll {
                LoadLibrary("NTDLL.DLL"),
                [](void* h){if (h)FreeLibrary((HMODULE)h); }
                };

                > шаблон нужен лишь чтобы можно было пихать и функции, и лямбды, и std::function
                И даже аллаха, если у него есть operator ().
                Ответить
                • Причём именно принимающий void* и возращающий void?
                  > (HMODULE)h
                  Забавно, везде такие шаблоны модные, а при использовании всё равно сишный говнокаст писать.
                  Ответить
                  • так это использование std::shared_ptr не по назначению
                    Ответить
                  • > принимающий void*
                    Если точнее - T*, где T* - что-нибудь, во что может кастануться указатель на первый аргумент. Насчёт возврата void - х.з., должен проканать и не void, просто заигнорит результат.

                    В общем это функция, которую unique_ptr будет вызывать для освобождения указателя.

                    > сишный говнокаст
                    Причём этот HMODULE и есть void *, емнип.
                    Ответить
                • Зачем тебе уникью птр? std::shared_ptr же удобнее и функциональнее:
                  std::shared_ptr<void> _ntdll {
                  LoadLibrary("NTDLL.DLL"),
                  [](void* h){if (h)FreeLibrary((HMODULE)h); }
                  };
                  Ответить
                  • > тебе
                    Мне? :) Не надо мне приписывать код ОП'а...
                    Ответить
    • Ваше с++ - говно, на с++ кодят только динозавры.
      Ответить
      • Уже вижу кто-то начал флудить и троллить с грустным лицом, периодически обновляя сток
        Ответить
      • а как же Питухи?
        Ответить
      • Два инкремента одной переменной в одном выражении — это UB.
        Ответить
        • Ваше с++ - говно; на с++ кодят только динозавры;
          fxd
          Ответить
          • Получается, что динозавры кодят на более новом языке, чем тот, который является говном?
            Ответить
      • RRRAAAAAWWWRRRR!!11
        Ответить

    Добавить комментарий