• C++: сеанс спонтанной археологии и почему не стоит использовать вариативные функции в стиле C

    Началось все, как водится, с ошибки. Я первый раз работал с Java Native Interface и делал в C++ части обертку над функцией, создающей Java объект. Эта функция — CallVoidMethod — вариативна, т.е. помимо указателя на среду JNI, указателя на тип создаваемого объекта и идентификатора вызываемого метода (в данном случае конструктора), она принимает произвольное число других аргументов. Что логично, т.к. эти другие аргументы передаются вызываемому методу на стороне Java, а методы могут быть разные, с разным числом аргументов любых типов.

    Соответственно и свою обертку я тоже сделал вариативной. Для передачи произвольного числа аргументов в CallVoidMethod использовал va_list, потому что по-другому в данном случае никак. Да, так и отправил va_list в CallVoidMethod. И уронил JVM банальным segmentation fault.

    За 2 часа я успел перепробовать несколько версий JVM, от 8-ой до 11-ой, потому что: во-первых это мой первый опыт с JVM, и в этом вопросе я StackOverflow доверял больше, чем себе, а во-вторых кто-то на StackOverflow посоветовал в таком случае использовать не OpenJDK, а OracleJDK, и не 8, а 10. И лишь потом я наконец заметил, что помимо вариативной CallVoidMethod есть CallVoidMethodV, которая произвольное число аргументов принимает через va_list.

    Что мне больше всего не понравилось в этой истории, так это то, что я не сразу заметил разницу между эллипсисом (многоточием) и va_list. А заметив, не смог объяснить себе, в чем принципиальное отличие. Значит, надо разобраться и с эллипсисом, и с va_list, и (поскольку речь все-таки о C++) с вариативными шаблонами.
    Читать дальше →
  • Полёт свиньи, или Оптимизация интерпретаторов байт-кода


      "No matter how hard you try, you can't make a racehorse out of a pig. You can, however, make a faster pig" (комментарий в исходном коде Емакса)

      Всем известен тот факт, что свиньи не летают. Не менее популярно мнение о том, что интерпретаторы байт-кодов как техника исполнения языков высокого уровня не поддаются ускорению без применения трудоёмкой динамической компиляции.


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

      Читать дальше →
    • Портирование Quake3


        В операционной системе Embox (разработчиком которой я являюсь) какое-то время назад появилась поддержка OpenGL, но толковой проверки работоспособности не было, только отрисовка сцен с несколькими графическими примитивами.


        Я никогда особо не интересовался геймдевом, хотя, само собой, игры мне нравятся, и решил — вот хороший способ развлечься, а заодно проверить OpenGL и посмотреть, как игры взаимодействуют с ОС.


        В этой статье я расскажу о том, как собирал и запускал Quake3 на Embox.

        Читать дальше →
      • Как сделать расширение на PHP7 сложнее, чем «hello, world», и не стать красноглазиком. Часть 2

        • Tutorial

        Краткое содержание первой части


        В первой части я сделал болванку расширения, заставил ее правильно работать в IDE Clion, написал функцию-аналог my_array_fill() и проверил ее работоспособность в php.

        Что теперь?


        Теперь я запилю код библиотеки libtrie в наше расширение.

        Немного расскажу как можно заставить работать старые php5 расширения в php7.
        Дальше я сделаю несколько основных функций из этой библиотеки в php и проверю, что получилось.
        Читать дальше →
        • +16
        • 3,5k
        • 8
      • Надежность контрольной суммы CRC16

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

          У нас имеется устройство, которое осуществляет интенсивный обмен по внутренней шине RS485, число проходящих пакетов составляет порядка нескольких тысяч в секунду, каждый пакет имеет длину в 7 байт, два из которых предназначены для хранения контрольной суммы CRC16 в ее CMS варианте (полином = 0x8005, стартовое значение = 0xFFFF). Прием осуществляется в FIFO-буфер, который сдвигается вверх с вытеснением после приема каждого последующего байта. Индикатором получения реального пакета является факт совпадения его контрольной суммы со значением, переданным в самом пакете. Никаких заголовков или дополнительных параметров.

          Проблема заключалась в следующем – периодически, примерно раз в 5 минут, при передаче данных проскакивал пакет, данные которого давали выброс данных для одного из каналов, причем чаще всего выброс происходил до одного и того же значения. Сначала мы смотрели в сторону физических коллизий, но дело оказалось в другом – время от времени в буфере, где собирались полученные данные, оказывался пакет, состоящий из конца предыдущего пакета и начала следующего, причем контрольная сумма у такого комбинированного пакета оказывалась верной. То есть, налицо коллизия контрольной суммы: пакет не имеет смысла, но дает верную контрольную сумму.
          Читать дальше →
        • Как сделать расширение на PHP7 сложнее, чем «hello, world», и не стать красноглазиком. Часть 1

          • Tutorial

          Зачем?


          Я пишу эту статью для того, чтобы путь, который у меня занял в общей сложности не меньше года, читатель смог пройти за пару часов. Как показал мой личный опыт, просто программировать на Си несколько легче, чем заставить работать серьезное расширение для PHP. Здесь я максимально подробно расскажу вам о том, как сделать расширение на примере библиотеки libtrie, реализующей префиксное дерево, более известное как trie. Я буду писать и параллельно выполнять описываемые действия на свежеустановленной системе Lubuntu 18.04.

          Начнем.
          Читать дальше →
        • Хитрое префиксное дерево Си реализация

            image

            Введение


            Прошло долгих четыре месяца с момента публикации статьи о моей попытке низкоуровневой реализации префиксного дерева. Несмотря на все мои старания потолок на который оказалась способна моя прошлая реализация префиксного дерева был ~80 тыс. слов в секунду. Я потратил тогда кучу сил и времени, но полученный результат сгодился бы только как лабораторная работа по информатике.

            Многие тогда мне говорили: «Не изобретай велосипед, который уже изобрели! Используй готовое решение». Сложность в том, что мне не удавалось использовать что-то, что я не понимаю хотя бы в общих очертаниях.

            Префиксное дерево я кажется понял, и вот чего удалось добиться.
            Читать дальше →
          • Как правильно и неправильно спать

              Не так давно мимо нас пробегала неплохая статья об ужасном состоянии производительности современного ПО (оригинал на английском, перевод на Хабре). Эта статья напомнила мне об одном антипаттерне кода, который встречается весьма часто и в общем кое-как работает, но приводит к небольшим потерям производительности то тут, то там. Ну, знаете, мелочь, пофиксить которую руки никак не дойдут. Беда лишь в том, что десяток таких «мелочей», разбросанных в разных местах кода начинают приводить к проблемам типа «вроде у меня последний Intel Core i7, а прокрутка дёргается».

              Я говорю о неверном использовании функции Sleep (регистр может отличаться в зависимости от языка программирования и платформы). Итак, что же такое Sleep? Документация отвечает на этот вопрос предельно просто: это пауза в выполнении текущего потока на указанное количество миллисекунд. Нельзя не отметить эстетическую красоту прототипа данной функции:

              void Sleep(DWORD dwMilliseconds);

              Всего один параметр (предельно понятный), никаких кодов ошибок или исключений — работает всегда. Таких приятных и понятных функций очень мало!

              Ещё большим уважением проникаешься к этой функции, когда читаешь, как она работает
              Функция идёт к планировщику потоков ОС и говорит ему «мы с моим потоком хотели бы отказаться от выделенного нам ресурса процессорного времени, сейчас и ещё на вот столько-то миллисекунд в будущем. Отдайте бедным!». Слегка удивлённый подобной щедростью планировщик выносит функции благодарность от имени процессора, отдаёт оставшийся кусок времени следующему желающему (а такие всегда найдутся) и не включает вызвавший Sleep поток в претенденты на передачу ему контекста выполнения на указанное количество миллисекунд. Красота!

              Что же могло пойти не так? То, что программисты используют эту замечательную функцию не для того, для чего она предназначена.
              Читать дальше →
            • CPU Design: Эзотерический язык LMCode

              • Tutorial

              Часть I
              Часть II
              Часть III
              Часть IV

              Четвёртая часть цикла посвящена созданию интерпретатора некого эзотерического языка LMCode, в основе которого лежит архитектура Little Man Computer. О Little Man Computer можно прочитать в предыдущих статьях.

              • Пусть команде INP соответствует ,
              • команде OUT соответствует .
              • команде ADD соответствует +
              • команде SUB соответствует
              • команде STA соответствует ~
              • команде LDA соответствует ^

              Напишем программу, которая загружает число из устройства ввода в аккумулятор, сохраняет число в памяти, прибавляет число из памяти к аккумулятору (удваивает число), и выводит удвоенное число в устройство вывода.

              На ассемблере LMC эта программа будет выглядеть так (начальной ячейкой пусть будет 20)

               INP
               STA 20
               ADD 20 
               OUT
              

              Читать дальше →
              • +14
              • 3,6k
              • 4
            • STM32H7 — настройка тактирования без HAL

                Не так давно компания STM выпустила на рынок очень мощную, по меркам микроконтроллеров, линейку кристаллов STM32H7. Что меня в ней привлекло:

                • повышенная частота ядра до 400 МГц
                • увеличенный объем ОЗУ, до 1 МБ
                • 16 разрядный АЦП
                • pin-to-pin совместимость с серий F7

                Отлично подумал я, запаял на плату кристалл STM32H743IIT6 вместо STM32F746IGT6 и начал новый проект в SW4STM32.
                И вот что из этого получилось.

              Самое читаемое