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

    −2

    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
    27. 27
    28. 28
    29. 29
    30. 30
    31. 31
    32. 32
    33. 33
    34. 34
    35. 35
    36. 36
    37. 37
    38. 38
    39. 39
    40. 40
    41. 41
    42. 42
    43. 43
    44. 44
    45. 45
    46. 46
    47. 47
    48. 48
    49. 49
    50. 50
    51. 51
    52. 52
    53. 53
    54. 54
    55. 55
    56. 56
    57. 57
    58. 58
    59. 59
    60. 60
    61. 61
    62. 62
    63. 63
    64. 64
    65. 65
    66. 66
    67. 67
    68. 68
    69. 69
    70. 70
    71. 71
    72. 72
    73. 73
    namespace bt {
    #define MEMNULL \
    	_FORCEINLINE void* operator new(size_t) { return 0; } \
    	_FORCEINLINE void operator delete(void* ) { }
    
    #define MEMDEFAULT(classname) \
    	_FORCEINLINE void* operator new(size_t size) { return extFunctions.CreateMem((unsigned int)size, 0); } \
    	_FORCEINLINE void operator delete(void* val) { extFunctions.DeleteMem(val, 0); }
    
    #define MEMMANAGER(classname) \
    	_FORCEINLINE void* operator new(size_t size) { return bt::internalmemmanager.getNew((unsigned int)size); } \
    	_FORCEINLINE void operator delete(void* val) {bt::internalmemmanager.freeThis(val,sizeof(classname));}
    
    #define MEMMANAGERCLEAN(classname) \
    	_FORCEINLINE void* operator new(size_t size) { return bt::internalmemmanager.getNewClean((unsigned int)size); } \
    	_FORCEINLINE void operator delete(void* val) { bt::internalmemmanager.freeThis(val,sizeof(classname)); }
    
    	class memManagerExport {
    	public:
    		MEMDEFAULT(memManagerExport)
    
    		BT_API memManagerExport(unsigned int size);
    
    		BT_API virtual ~memManagerExport();
    
    		/// destroy all memory segments and free list of free pointers
    		BT_API void _free();
    		/// return pointer to new object and create new segment of objects if need.
    		BT_API void *_addAlloc();
    		/// return pointer to free object
    		BT_API void *_getFree(unsigned int size);
    		/// add pointer to list of free
    		BT_API void _appendToFree(_voidint idat);
    		/// mark pointer to free ???
    		BT_API void _markFree(void* val);
    		/// return number object in segment
    		BT_API unsigned int _valid(unsigned int id);
    		/// return segment number
    		BT_API unsigned int _segid(unsigned int id);
    		/// prepare calculation for object size
    		BT_API void _calcsize(unsigned int size);
    
    	private:
    		enum States {
    			VALIDED = 0x011F1C01,
    			FREE = 0
    		};
    
    		unsigned int fisVal;
    		struct p_smemManager *fargs;
    	};
    
    	class memManager: public memManagerExport {
    	public:
    		MEMDEFAULT(memManager)
    
    		_FORCEINLINE memManager(unsigned int size):memManagerExport(size) {}
    
    		_FORCEINLINE ~memManager() {}
    
    		/// create memory for object
    		_FORCEINLINE void *getNew(unsigned int size) {return (void*)_getFree(size);}
    		/// delete memory for object
    		_FORCEINLINE void freeThis(void * val) {_appendToFree((_voidint)val);}
    		/// destroy all memory segments and free list of free
    		_FORCEINLINE void free() {_free();};
    	};
    
    	class globalMemManager {
    	public:
    		MEMDEFAULT(globalMemManager)
    
    }

    Давайте ржать

    Запостил: foxes, 10 Марта 2016

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

    • не вписался:

      BT_API globalMemManager();
      BT_API ~globalMemManager();

      /// выделяет сегмент быстрой памяти из имеющегося запаса
      BT_API void* getNew(unsigned int size);
      /// выделяет сегмент быстрой памяти из имеющегося запаса
      BT_API void* getNewClean(unsigned int size);
      /// освобождает сегмент быстрой памяти для повторного использования
      BT_API void freeThis(void*val,unsigned int size);

      /// выделяет сегмент памяти стандартными средствами если сегмент запрашиваемого размера не обслужывается.
      BT_API void* cashalloc(unsigned int size);
      /// освобождает сегмент памяти проверяя способ его выделения.
      BT_API void cashfree(void* val,unsigned int size);

      /// Обработчик многопоточных блокировок использования памяти
      BT_API void manage();
      _FORCEINLINE volatile bool &lock() { return flock; }
      _FORCEINLINE volatile _voidint &lockId() { return flockid; }
      _FORCEINLINE volatile _voidint &canLeave() { return fcanleaveid; }
      tfSTDCALL_uint_FUNC isThread;

      /// текущий уровень выравнивания памяти
      _FORCEINLINE unsigned int _olevel() {return olevel;}

      private:
      enum States {
      VALIDED = 0x011F1C01,
      FREE = 0
      };

      unsigned int fisVal;
      struct p_globalMemManager *fmanagers;
      unsigned int olevel;
      volatile bool flock;
      volatile _voidint flockid;
      volatile _voidint fcanleaveid;

      unsigned int alignSize(unsigned int size);
      _voidint alignPointer(_voidint p);
      void init();
      void cleaner();
      };
      Ответить
    • http://govnokod.ru/19596
      Ответить
    • Чертовски сурово.
      А в чем назначение MEMNULL? Зачем нужен неаллоцируемый в куче объект?
      Ответить
      • > Зачем нужен неаллоцируемый в куче объект?
        Чтобы его не аллоцировали в куче...

        К слову, из не nothrow оператора new нельзя возвращать NULL. Это UB, т.к. никто не проверяет результат обычного new...
        Ответить
      • Применил MEMNULL: http://ideone.com/Mqbc1M

        Искренне надеюсь, что автор не для этого его запилил...
        Ответить
        • По факту это заглушка для генерации исключения. используется для абстрактных/базовых классов. Поскольку пустым оператор не может быть там стоит return 0; Но цель была сделать его именно с 0, чтобы код этого метода мог выкинуться компилятором при оптимизации. так как void * GccDontWantReturnANullFromNew = NULL; оптимизируется до операции чтения GccDontWantReturnANullFromNew - mov eax,[GccDontWantReturnANullFromNew] вместо xor eax,eax. Также используется для уменьшения кода за счет удаления реализации пустых методов.
          Ответить
          • > используется для абстрактных/базовых классов
            Ну на них же никто никогда не сможет позвать new... Почему бы не оставить для них дефолтные реализации операторов (которые всяко не попадут в бинарник, даже если сгенерятся, т.к. никто их не вызовет)?

            > генерации исключения
            И где же оно, кхм, генерится? Возврат NULL'а из new - просто провокация на UB. О чём нам как бы намекает gcc, если вернуть просто NULL, а не ту самую глобалку.

            P.S. Если хочешь невызываемые new/delete - просто в приват их спрячь, да и всё... И реализации им не пиши.
            Ответить
            • Да такой момент действительно имеет место быть, но только для абстрактных классов. Дефолтные реализации очень сильно флудят кодом, в некоторых случаях при отладки мешает, ну и для общего стиля. Также они вылезают при экспорте.
              Например: я делаю что то на подобии вектора который не должен создаваться new MyVec. например этот класс содержит всего один указатель внутри и сам по себе является оберткой к динамическому объекту у которого нет определенного типа, а следовательно и размера. То есть для таких классов делать new тоже самое что делать new void*. Соответственно тот кто так сделает получит исключение.
              Ответить
              • Может лучше вот так?
                class foo {
                private:
                    void* operator new(size_t);
                    void operator delete(void*);
                    void* operator new[](size_t);
                    void operator delete[](void*);
                }
                Гарантии:
                1) Вызвать new, delete, new[], delete[] для этого типа невозможно, компилятор сразу об этом скажет (т.е. не надо ждать запуска программы и мифического исключения).
                2) Кода у этих методов вообще нет (о чём тебе скажет линкер, если уберёшь private и всё-таки вызовешь).
                Ответить
                • Да мой пример не очень, но все таки реализация new, delete... в твоем примере существует причем для каждого класса своя, а в моем случает это будет только одни new для всех подобных классов, это сжимает код. В общем достаточно узконаправленное использование.
                  Предположим что мне все таки нужно вызвать new MyVec - это для динамических случаев, кода у меня есть ассоциативный список конструкторов для имен классов.
                  Опять же достаточно добавить class export foo.
                  Ответить
                  • > только одни new для всех подобных классов
                    Так твой MEMNULL надо юзать на глобальном уровне, а не внутри классов?

                    > в твоем примере
                    Где она? Линкер меня обманывает, когда говорит, что её нету?
                    Ответить
                    • foxes
                      > Предположим что мне все таки нужно вызвать new MyVec
                      bormand
                      > Где она?
                      foxes
                      > а в моем случает это будет только один new
                      bormand
                      > а не внутри классов?
                      template <typename T>

                      class MapName {
                      public:
                      MEMNULL
                      ...
                      }
                      Ответить
                      • ну так и какие проблемы вставить в шаблон вместо макроса несколько строк, в которые он раскрывается?
                        Ответить
                        • Ну он же в несколько разных классов хочет втыкать.
                          Ответить
                  • > нужно вызвать new MyVec
                    И получить NULL? Может проще не добавлять такие классы в список создаваемых по имени, раз всё равно ничего полезного не получится?

                    > class export foo
                    Это какая-то фишка msvc? Она помечает все методы класса как dllexport, даже приватные?
                    Ответить
                    • > Это какая-то фишка msvc?
                      нет только для public, написал же выше.
                      // * MSVC - компилятор Microsoft Visual C++
                      // * INTEL - компилятор Intel C++
                      // * BORLAND - компилятор Borland C++
                      // * GCC - компилятор GNU C/C++
                      // * MINGW - компилятор MinGW

                      кажется после MINGW я забил на твой вариант в некоторых классах. А может это был GCC для Эльбруса.
                      Ответить
                    • > раз всё равно ничего полезного не получится?
                      Да для общего стиля - где куча кода заменяется на одну инструкцию и просто генерит 0.
                      Реально можно много чего не делать и просто взять готовое. Например BOOST. Или поставить MEMNULL и без заморочек получить размер проекта в 96кб. http://www.gamedev.ru/files/?id=104502
                      Ответить
      • Что бы писать MEMNULLары
        Ответить

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