Как стать автором
Поиск
Написать публикацию
Обновить
138.6

C *

Типизированный язык программирования

Сначала показывать
Порог рейтинга

Что ты сделал для хип-хопа IT-инфраструктуры в свои годы? Писал UEFI и BMC для высоконагруженного оборудования 

В YADRO есть распределенная команда, которая разрабатывает и сопровождает собственные программные реализации UEFI (BIOS) и BMC. Для самого разного оборудования — от серверов до телеком- и клиентского оборудования. 

Что делают BIOS и BMC в продуктах
Что делают BIOS и BMC в продуктах

Познакомиться с командой → 

Какие задачи выполняют в команде BIOS/BMC: 

  • Реализуют программную поддержку новых аппаратных продуктов компании, определяют протоколы и методы взаимодействия между программными и аппаратными компонентами продуктов YADRO.

  • Проводят верификацию микрокода и выполняют проверку прошивок микросхем всех продуктов компании. Выстраивают стратегию тестирования.

  • Исследуют новые программные и аппаратные технологии для применения в продуктах. Рефакторят код для повышения производительности.

  • Придумывают методы безопасного обновления прошивок BIOS и BMC, чтобы обеспечить минимальный или нулевой даунтайм.

  • Добавляют новые фичи и меняют существующие — от WebUI до политик управления аппаратными компонентами.

Команде нужно больше инженеров — разработчиков на С/C++, тестировщиков, автоматизаторов и техлидов. Знакомься с вакансиями на сайте и вовлекайся в трушные инженерные задачи на современном технологическом стеке. 

Теги:
+9
Комментарии0

Последовательность Фибоначчи может конвертировать мили в километры с небольшой погрешностью

5 миль ≈ 8 км (5 и 8 - числа Фибоначчи). Реальность: 5 миль = 8.04672 км.

Почему?
1 миля = 1.609344 километра (точное значение).
Золотое сечение (φ) ≈ 1.618034

Погрешность возникает потому что отношение Fₙ₊₁ / Fₙ стремится к φ ≈ 1.618034, а точное соотношение миля/км = 1.609344.

Относительная погрешность: (1.618034 - 1.609344) / 1.609344 * 100% ≈ 0.54%.

Решил по фану реализовать конвертор милей в километры на C. Ссылка тут.

Advanced distance converter: miles to kilometers
Usage: ./bin/fib_miles2km [OPTIONS] [distance]

Options:
  -h, --help                     Show help information
  -f, --fib=ARG                  Convert miles to km using basic Fibonacci
  -b, --basic=ARG                Convert miles to km using standard formula
  -i, --fib-interp=ARG           Convert using Fibonacci interpolation
  -c, --fib-cache=ARG            Convert using cached Fibonacci
  -g, --fib-golden=ARG           Convert using golden ratio

Не знаю зачем, но прикольно :)

Теги:
+18
Комментарии1

Как создать простейшую модель GPIO для QEMU

Предлагаю два варианта, которые я условно решил назвать MMIO и PCI. Последний — тоже MMIO, но в QEMU они добавляются разными путями. Начнем с сердца любой MMIO-модели — апертуры.

Апертура и адресное пространство

Как я упоминал в одной из своих статей, любое MMIO-устройство — это MemoryRegion с заданными шириной доступа и размером. Для того, чтобы он был виден CPU или другому устройству, такому как DMA, его нужно разместить в соответствующем адресном пространстве — например, пространстве, назначенном для cpu0:

      0x0                                    0xffffffffffffffff
      |------|------|------|------|------|------|------|------|
0:    [                    address-space: cpu-memory-0        ]
0:    [                    address-space: memory              ]
                    0x102000           0x1023ff
0:                  [             gpio        ]

В любое время можно посмотреть существующие адресные пространства и регионы памяти в мониторе QEMU:

(qemu) info mtree
[...]
address-space: cpu-memory-0
address-space: memory
  0000000000000000-ffffffffffffffff (prio 0, i/o): system
    0000000000102000-00000000001023ff (prio 0, i/o): gpio
[...]

Тогда в модели устройства нам нужно всего лишь создать такой регион и назначить ему соответствующие функции записи и чтения:

static const MemoryRegionOps mmio_mmio_ops = {
    .read = mmio_gpio_register_read_memory,
    .write = mmio_gpio_register_write_memory,
    .endianness = DEVICE_NATIVE_ENDIAN,
    .valid = {
        .min_access_size = 4,
        .max_access_size = 4,
    },
};
 
[...]
memory_region_init_io(iomem, obj, &mmio_mmio_ops, s,
                      "gpio", APERTURE_SIZE);
[...]

Фактически это означает, что все семейство инструкций Load/Store будет вызывать mmio_gpio_register_read_memory()/mmio_gpio_register_write_memory() при совпадении адреса чтения/записи с адресом региона в адресном пространстве.

static uint64_t mmio_gpio_register_read_memory(void *opaque, hwaddr addr, unsigned size);
static void mmio_gpio_register_write_memory(void *opaque, hwaddr addr, uint64_t value, unsigned size);

Передаваемые аргументы и возвращаемое значения интуитивно понятны. Отмечу, что hwaddr addr — это адрес относительно начала нашего региона, а не абсолютный адрес.

Нам остается лишь создать устройство и добавить его регион в файле машины:

gpio = qdev_new(TYPE_MMIO_GPIO);
sysbus_mmio_map(SYS_BUS_DEVICE(gpio), 0, ADDRESS);

Почти десять лет назад Никита Шубин, ведущий инженер по разработке СнК в YADRO, сделал возможность чтения и записи GPIO для QEMU. Читайте первую часть трилогии о долгом пути до GPIO в QEMU.

Теги:
+1
Комментарии0

В языке C (и C++ тоже) существуют три различных типа: char, unsigned char и signed char.

При этом типы unsigned char и signed char предназначены для хранения чисел. "Предназначены" стоит воспринимать как "рекомендуется использовать для этих целей", фактически, программист волен в этих типах хранить и, выражаясь терминами языка Си, символы.

Когда выбрать unsigned char, а когда signed char? Нужно подумать сколько значений может принимать ваша переменная. Например, если вы храните результат ввода с клавиатуры и у вас вообще не стоит проверка на длину введенного числа, то ... То ваша программа порочна. Следует ограничивать предельную размерность всех данных. Итак, если у вас пользователь вводит
число из диапазона [0..255], тогда используйте unsigned char. Если у вас переменная может быть в диапазоне [-128..127] то используйте signed char. И так далее. Если у вас числа уже не помещаются даже в uint64_t, гуглите Длинная арифметика.

Тип char предназначен для хранения только символов. В зависимости от настроек компилятора char при компиляции транслируется или в signed char или в unsigned char. Хранение чисел в char возможно, но является признаком быдлокода.

char a = 'a'; //верно
char b = 200; //задумайтесь, может тип указать как uint8_t ?

Отдельно хочу отметить, что в 1999 году уже до всех дошло, что каждый раз писать ансигнед чар долго, очень долго. Были введены синонимы (typedef) в файле stdint.h

typedef unsigned char uint8_t;
typedef signed char int8_t;

Я рекомендую вам использовать эти синонимы вместо длинных названий сигнед чар и ансигнед чар.

К слову. Крайние значения для каждого типа хранятся в limits.h. Я напоминаю, что использование магических чисел - плохая практика. Поэтому обратите внимание на возможность написания UCHAR_MAX вместо 255 и так далее см. вики

Для тех, кто пишет код под 8-bit архитектуры (привет, atmega) но планирует в дальнейшем переход на другие платформы, обратите внимание на такие типы, как uint_least8_t...

Теги:
+1
Комментарии0

LLVM IR: что это такое?

Главной особенностью LLVM является промежуточное представление кода (англ. Intermediate Representation, IR), форма, которую использует LLVM для представления кода в компиляторе. LLVM IR был разработан для выполнения функций промежуточного анализа и преобразований внутри оптимизатора компилятора. Ее создание имело целью решение множества специализированных задач, включая поддержку легковесных оптимизаций среды выполнения, кроссфункциональные и межпроцедурные оптимизации, полный анализ программы и агрессивные реструктурирующие преобразования. Промежуточное представление кода определено как язык первого порядка с четкой семантикой.

IR (Intermediate Representation) в контексте LLVM — это промежуточное представление кода. Это низкоуровневое, независимое от платформы и типобезопасное представление программного кода, которое используется в качестве промежуточного языка между интерфейсной частью и серверной частью компилятора.

define i32 @add1(i32 %a, i32 %b) {
entry:
  %tmp1 = add i32 %a, %b
  ret i32 %tmp1
}

define i32 @add2(i32 %a, i32 %b) {
entry:
  %tmp1 = icmp eq i32 %a, 0
  br i1 %tmp1, label %done, label %recurse

recurse:
  %tmp2 = sub i32 %a, 1
  %tmp3 = add i32 %b, 1
  %tmp4 = call i32 @add2(i32 %tmp2, i32 %tmp3)
  ret i32 %tmp4

done:
  ret i32 %b
}

Этот код LLVM IR соответствует следующему коду на языке C, обеспечивающему возможность сложения целых чисел двумя разными способами:

unsigned add1(unsigned a, unsigned b) {
  return a+b;

}
// возможно не самый лучший способ сложения двух чисел
unsigned add2(unsigned a, unsigned b) {
  if (a == 0) return b;
  return add2(a-1, b+1);
}

Как видно из этого примера, LLVM IR — низкоуровневый RISC-подобный набор виртуальных инструкций. Как и настоящий набор инструкций RISC, он поддерживает линейные последовательности простых инструкций (сложение, вычитание, сравнение и ветвление). Эти инструкции имеют трехадресную форму. Это значит, что они берут некоторое количество входных данных и вычисляют результат в другом регистре. LLVM IR поддерживает метки и в целом выглядит как необычная форма языка ассемблера.

Строго говоря, промежуточное представление LLVM является четко определенным и единственным интерфейсом оптимизатора. Это означает, что всё, что необходимо знать, чтобы писать фронтенды для LLVM, это: что такое LLVM IR, как он работает и какие инварианты ему необходимы. Так как LLVM IR имеет текстовую форму, то имеет смысл создавать фронтенд, который выводит LLVM IR в виде текста, а затем отправляет его на оптимизатор и необходимый генератор кода при помощи каналов Unix.

Теги:
Всего голосов 5: ↑3 и ↓2+3
Комментарии0

unraisable exceptions в питоне

Мы все с вами привыкли, что в питоне можно "зарайзить" исключение в любой момент: raise Exception
Но, что если в какой-то момент времени мы не можем вызывать исключение?

Простейший пример: что произойдет при запуске такого скрипта?

# ex.py
class BrokenDel:
    def __del__(self):
        raise ValueError('del is broken')

obj = BrokenDel()
del obj
print('done!')  # будет ли выведено?

Тут может быть два варианта:

  1. Или del вызовет ValueError и программа завершится

  2. Или случится какая-то магия, ошибка будет вызвана, напечатается, но программа продолжится

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

» python ex.py
Exception ignored while calling deallocator :
Traceback (most recent call last):  File "/Users/sobolev/Desktop/cpython/ex.py", line 3, in __del__    raise ValueError('del is broken')
ValueError: del is broken
done!

Знакомьтесь – unraisable exceptions 🤝

Как оно работает?

В некоторых местах C кода у нас есть необходимость вызывать исключения, но нет технической возможности. Пример, как выглядит упрощенный dealloc для list?

static void
list_dealloc(PyListObject *op)
{
    Py_ssize_t i;
    PyObject_GC_UnTrack(op);  // убираем объект из отслеживания gc
    if (op->ob_item != NULL) {
        i = Py_SIZE(op);
        while (--i >= 0) {
            // уменьшаем счетчик ссылок каждого объекта в списке
            Py_XDECREF(op->ob_item[i]);  
        }
        op->ob_item = NULL;
    }
    PyObject_GC_Del(op);
}

А, как вы можете знать, чтобы в C коде вызвать ошибку, нужно сделать две вещи:

  • Взывать специальное АПИ вроде PyErr_SetString(PyExc_ValueError, "some text")

  • И вернуть NULL как PyObject * из соответствующих АПИ, показывая, что у нас ошибка. Если вернуть NULL нельзя, то мы не можем поставить ошибку в текущий стейт интерпертатора. А тут у нас void и вернуть вообще ничего нельзя. Потому приходится использовать вот такой подход с unraisable exception

Ошибку мы "вызываем" через специальные АПИ:

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

В питоне оно используется где-то 150 раз. То есть – прям часто. Примеры:

  • Ошибки при завершении интерпретатора, попробуйте сами:

import atexit
def foo():
    raise Exception('foo')
atexit.register(foo)
  • Ошибки внутри sys.excepthook

  • Ошибки внутри gc

  • Ошибки внутри логики установки ошибок (вдруг память кончилась, например) 🌚️️️️

  • И многое другое

Пользовательское АПИ

Ну и конечно же, есть специальный хук для обработки таких ошибок: sys.unraisablehook

Он может выполнять любой пользовательский код, который мы установим при старте приложения.

Например, pytest использует кастомный хук, чтобы валить тесты при возникновении такой ситуации. Что логично.

Нравится контент про технику и устройство технологий? Присоединяйся к каналу @opensource_findings в телеге; там много такого.

Обсуждение: знали ли вы про такую особенность? Приходилось ли где-то в мониторинге особо настраивать?

Теги:
Всего голосов 9: ↑8 и ↓1+10
Комментарии1

Бета-тестирование: обновлённый парсер для анализа кода на языках C и C++

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

Уже больше года команда разработки PVS-Studio кропотливо работает над обновлением собственного парсера для анализа кода на языках C и C++. Это большое обновление, хоть и не видно для большинства пользователей. Оно служит фундаментом для дальнейших усовершенствований анализатора.

Отличная новость для пользователей Linux: по вашим многочисленным просьбам мы добавили возможность тестирования на Linux! Теперь пользователи обеих операционных систем (Windows и Linux) могут помочь нам в улучшении продукта. Если вы ещё не участвовали в тестировании, сейчас самое время присоединиться!

До 6 июня 2025 года вы сможете протестировать специальную версию анализатора. На этом этапе для нас крайне важна обратная связь от пользователей. К релизу мы хотели бы удостовериться, что новый компонент не приведёт к существенному замедлению анализа или нестабильности у пользователей.

Как присоединиться к тестированию?

Просто заполните специальную форму на нашем сайте. В ответном письме вы получите подробную информацию о тестировании, инструкцию по установке тестовой версии и, при необходимости, временную лицензию на PVS-Studio.

Расскажите о своём опыте!

Если во время использования анализатора вы заметите баги, падения, странные срабатывания или замедление, пожалуйста, сообщите нам об этом! Для этого вы можете ответить на письмо, которое мы присылали ранее, или написать через форму обратной связи. Любые отзывы, баг-репорты и предложения будут очень полезны для нас.

Если хотите поделиться этой статьей с англоязычной аудиторией, то прошу использовать ссылку на перевод: Mikhail Gelvikh. Beta testing: updated parser for C and C++ code analysis.

Теги:
Всего голосов 3: ↑2 и ↓1+1
Комментарии0

Тяжела и неказиста жизнь простого программиста статических анализаторов кода

Команда PVS-Studio, содействуя разработке методики испытаний статических анализаторов под руководством ФСТЭК, составляла некоторые синтетические тесты. Писать синтетические тесты сложнее, чем кажется, и с их достоверностью всегда масса нюансов. Я никогда не любил синтетические тесты и продолжаю их не любить. Но что делать, они тоже нужны, когда речь заходит о необходимости подтвердить, что в анализаторах реализован определённый набор технологий.

Даже зная и понимая нюансы составления синтетических тестов, мы всё равно наступили на собственные грабли! Переиграли сами себя :)

Есть составленные нами тесты, в которых в функцию srand или её аналог передаётся константное значение. Это приводит к тому, что функция rand каждый раз будет генерировать одинаковую последовательность псевдослучайных чисел. Такой код, согласно ГОСТ Р 71207-2024, п. 6.3.г, может являться ошибкой некорректного использования системных процедур и интерфейсов, связанных с обеспечением информационной безопасности (шифрования, разграничения доступа и пр.).

Когда тесты подготавливались в Compiler Explorer, всё работало: PVS-Studio выдавал предупреждение V1057. А сейчас, когда код мило и скромно лежит в файлах, не работает. На Compiler Explorer работает, а вне — нет. Магия. Уже собрались баг в анализаторе искать.

Ах нет, всё просто. Файлы с тестами называются test_err_*.cpp. И в детекторе срабатывает исключение N4: "Находимся в файле, содержащем в названии слова check/test/bench". Тьфу. Причём получается, что анализатор прав: это действительно тест, а не настоящий баг :) Вот оно, несовпадение реальности и синтетических проверок в действии. Выкрутимся как-нибудь, но решил описать, так как случай интересный.

Зачем такое исключение? При разработке анализатора самое важно состоит не в том, чтобы выдать предупреждение, а в том, чтобы постараться не выдать лишнее. У всех анализаторов ложноположительных срабатываний всегда больше, чем хочется.

При экспертизе коллекции проектов стало ясно, что если это файлы с тестами, то писать srand(константа) абсолютно нормально. Более того, так специально делают, чтобы тесты вели себя повторяемо от запуска к запуску. Вот и было принято решение сделать соответствующее исключение. Теоретически это может скрыть реальную ошибку, но на практике в большой коллекции проектов, на котором мы прогоняем новые диагностические правила, такого не было. Зато в юнит-тестах этих проектов такое встречалось часто, и, соответственно, предупреждение оказывалось бессмысленным.

Был рад поведать немного интересного из жизни разработчиков статических анализаторов кода. А если хочется послушать что-то ещё, приглашаю на подкаст "Статический анализ по серьёзному" с моим участием 27 мая в 19:00 по Москве.

Теги:
Всего голосов 10: ↑10 и ↓0+14
Комментарии1

Всем привет, сделал чтение файла .3ds интересным способом

https://dpaste.com/838KNFEAU

тут стоит 36 потомучто читаю кубик. (Извиняюсь всё таки думаю это общее количество нод тоесть 24 должно быть)

for (int i = 0; i < 36; i++) суть в том, что мы проходим по дереву чанков линейно как я понял, но всё равно если поставить i<100 будет buffer overflow. Когда в консольном варианте можно поставить хоть 300 - для того чтоб быть уверенным что прошлись по всему дереву

единственный момент у меня на тесте кейфреймы 0 1 50 90 и при таких кейфреймах не прочтется 90 кейфрейм чанка скейл, который в самом конце

чтобы попасть в конец файла в блок с кейфреймами надо поставить 40 и если кому-то будет интересно заменить массивы на px,py,pz в блоке scale tag

и при портировании из блендера (у меня лтс 4.2.3) надо в .3ds всё выбрать и везде поставить галочки(кроме Hierarchy, Collection), чтобы (Local Coordinates System зафиксировалось )

на данный момент читается только красный кубик, те модели кубированные не читаются покачто - они прочтены через ассимп
на данный момент читается только красный кубик, те модели кубированные не читаются покачто - они прочтены через ассимп

всё таки работает, там просто по мелочи досмотреть.

Практическая составляющая этого - это приближение к составлению своего формата, не на основе этого, а через практику, понять, как хотелось бы лучше. Очень большой минус этого формата, что не портируются нормали и их приходится считать после загрузки. Следующий минус для Блендера и GL, а может и для общей практики - он дублирует вершины. Тоесть, если Obj кинет просто координаты на индексах от 8 вершин, то тут будет 14 вершин и 12 индексов. Это если сравнивать кубы.

вот исправленная ситуация с последним скейлом даже) https://dpaste.com/83WG7ZHPM

Теги:
Рейтинг0
Комментарии1

Учебник по Программированию Микроконтроллеров.

Господа,

Я сочинил книгу для библиотеки.

Предлагаю Вашему вниманию мой авторский учебник по программированию микроконтроллеров.

Всё утро его писал.

Называется
Практические Аспекты Программирования Микроконтроллеров

Эта книга адресована всем нынешним программистам микроконтроллеров, студентам технических ВУЗов, а также всем тем, кто думает заниматься программированием микроконтроллеров.

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

Скачать учебник можно по ссылке на git hub. Распространение приветствуется.

Есть две версии учебника: censored и unleashed.
Версию UnLeashed я буду высылать только под NDA в ответ на сообщение.

Учебник постоянно и непрерывно улучшается, исправляются опечатки, добавляются новые главы. Поэтому последняя версия лежит на git hub.

https://github.com/aabzel/Artifacts/blob/main/mcu_book_m

клонируйте репозиторий https://github.com/aabzel/Artifacts.git

git clone https://github.com/aabzel/Artifacts.git

И *.pdf окажется в папке mcu_book

Буду признателен за конструктивные предложения к улучшению материала в новых изданиях и за обнаружение опечаток.

Теги:
Всего голосов 30: ↑27 и ↓3+34
Комментарии64

Три проверенных метода организовать обмен прерываниями между машинами QEMU c KVM и без

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

Быстрая работа такой связки приятна при разработке/отладке и очень важна при массовом прогоне автотестов в CI. Как оптимизировать обмен прерываниями и какой подход к организации IQI вам подойдет — узнаете из статьи. А еще разберемся c:

  • устройством QEMU под капотом,

  • реализацией модели и драйвера,

  • добавлением прерываний MSI-X,

  • результатами замеров.

На бонус: десяток полезных материалов для изучения.

Теги:
Всего голосов 6: ↑5 и ↓1+5
Комментарии0

Книга по C и не только

Добрый день. Пару месяцев назад я закончил написание книги и выставляю её в открытый доступ: GitHub

В чём идея? Контент этой книги представляет собой не только обучение языку C, но и обучение большому количеству прикладных вещей с серьёзной глубиной погружения. Я постарался дать ответ на как можно большее количество вопросов, которые возникают в процессе изучения, оставив минимальное количество дыр в понимании, как всё работает.

Посмотреть .html файл книги можно на GitHub-е. Но он не рендерит MathJax, поэтому лучше скачать файл c-book.html локально. Можно как угодно (в том числе в issues) сообщать мне о нерабочем коде в примерах, опечатках, неправильных утверждениях с моей стороны. Буду также рад увидеть конструктивную критику. Возможно, в ответ на неё, я буду добавлять новые главы в книгу.

(Эта книга абсолютно точно не является рекламой Zig-а.)

Теги:
Всего голосов 22: ↑19 и ↓3+21
Комментарии12

Последний день регистрации на хакатон по интерфейсам «мозг-компьютер»

Хотите круто воплотить технологии будущего в реальность? Научить компьютер взаимодействовать с мозгом напрямую? Зажигать силой мысли лампочки и управлять компьютерными играми? Регистрируйтесь на BCI Hack Moscow.

Мы — компания Neiry. Наше  BCI-устройство Headband Pro и ПО Capsule считывают и записывают мозговую активность, и другие физиологические сигналы пользователя. А Capsule API позволяет использовать эти данные в других приложениях. На Хабре мы уже рассказывали про крутые кейсы, в которых задействованы наши разработки, про особенности Capsule и API

На хакатоне мы дадим участникам возможность создать прототипы продуктов на базе нейроинтерфейсов для Neiry Headband Pro и открытого API Neiry. Приглашаем разработчиков всех грейдов, студентов, нейроэнтузиастов. Язык нашего API — С, пригодятся знания в Python, SQL, аналитические навыки, опыт обращения с BCI. Если вам интересно поработать с нейроинтерфейсом, присоединяйтесь — оборудование выдадим бесплатно! Участвуйте самостоятельно или командой до 4 человек.

Регистрируйтесь сегодня: опишите в заявке свою крутую идею для нейроинтерфейсов. 20 сентября бесплатно выдадим участникам Neiry Headband Pro, для этого кто-то из команды должен быть в Москве. И всё, больше никаких блоков. Регистрируйтесь на BCI Hack Moscow и помогите сделать будущее — настоящим.

Теги:
Всего голосов 2: ↑2 и ↓0+6
Комментарии0

Ближайшие события

Привет! На связи команда Neiry Tech, мы занимаемся разработкой BCI-устройств и алгоритмов для использования с ними. Расскажем про ПО Capsule, считывающее и записывающее мозговую активность, и другие физиологические сигналы пользователя. И Capsule API — он помогает нам строить на основе классифицированных метрик и индексов итоговые приложения).

По сути Capsule — библиотека для десктопных и мобильных платформ с собственным графическим интерфейсом. Для быстродействия написали её на C++. Для Capsule API выбрали C.

Для вывода в API на разных платформах иногда пишем нативный код на Android или iOS, ну и обертку на C, чтобы API мог использовать широкий спектр разработчиков — за родным ноутом и в лаборатории.

Физиологические данные — сложные сигналы с высоким уровнем шума. Для их интерпретации нужно хорошо владеть методами цифровой обработки сигналов, погрузиться в предметную область, и как минимум понимать, чем фильтр Чебышева отличается от фильтра Баттерворта.

Головной боли добавляют особенности различных платформ — с плавающими задержками протокола BLE, или с реализацией вроде бы базовых вещей. Мы как-то обнаружили, что библиотека, занимающаяся быстрым преобразованием Фурье, нагружала новенькие Apple Silicon на 30%.

Сейчас Capsule и API позволяют работать с данными ЭЭГ и ФПГ на высоком для не лабораторного устройства уровне. Смотрим, радуемся и гордимся.

Хотите поработать с этими данными и нашим API? Присоединяйтесь к хакатону BCI Hack Moscow, регистрация до 15 сентября.

Теги:
Всего голосов 4: ↑4 и ↓0+8
Комментарии0

Почему бы не сделать runtime языка С++ проще и легче? почему бы не сделать его перенос в том числе проще? Когда я задался этим вопросом, я решил, что во чтобы то ни стало, я напишу свой RT, для тех, кто пишет под слабые машины, или тех, кто пишет под bare metal среду. результат вы можете посмотреть на гитхабе: вотъ

Когда я работал, я старался максимально всё упростить, при этом сохранив юзабельность. не знаю как для других, но лично мне было важно сохранить исключения, для меня это удобно. но в С++ они жутко дорогие из-за RTTI (RunTime Type Information), и на bare metal реализуется с большим напрягом. выход прост - использовать статусы вместо типов. но чтобы оставить всем знакомый и удобный синтаксис исключений и позволить функциям возвращать что-то вместо статуса, где это везде лепят, я переделал всё на тупо макросах :>

так же я понял, что сложность моей работы и сложность переносимости этой вещицы усложнится, если прям всё с нуля пилить, поэтому просто воспользовался libc, выпилив libc++. Пришлось сделать обёртки над new и delete, но это не так уж и сложно, просто вызывать malloc/free.

Так же я невероятно сильно намучился в попытках сделать всё используя стандартный синтаксис С++. Потратил несколько часов в попытках разобраться как оторвать исключения от использования rtti, возился в флагах, писать cxa, gxx и unwind с нуля, даже лез в ассемблерный код в попытках вырезать надоеду, но по итогу сдался и просто слепил всё из макросов.

Всем добра <3

Теги:
Всего голосов 3: ↑2 и ↓1+3
Комментарии2

Пару месяцев назад (точнее 15 месяцев и 12 дней) я выложил статью про исходный код PostgreSQL где рассказал про инфраструктуру узлов (struct Node) - с помощью него реализуется наследование, полиморфизм и все, все, все.

Вот уже как 2 месяца я работаю разработчиком PostgreSQL. Уже успел реализовать пару фич, закрыть несколько тасок и разбирался с другими проблемами.

Так вот, эти 2 месяца выдались веселыми. Кроме одного момента. Мне надоело постоянно возиться с этими нодами. Проблема в том, что есть наследование и многие переменные имеют свой базовый тип (если не самый базовый Node, который просто 1 поле тэга) - приходится постоянно лезть в (работаю в VS Code) watch панель и писать монструозные конструкции по типу ((RestrictInfo*)((RelOptInfo*)root->rtable[0])->another_field))->value (взято из головы). Причем - чем глубже спускаешься, тем громаднее и неповоротливее выражения становятся.

Я искал различные расширения или способы, чтобы облегчить себе жизнь, но ничего кроме встроенного pprint(Node *).

Мне это не понравилось. И я решил эту проблему по своему. Создал расширение для VS Code, которое позволяет просматривать все переменные и при необходимости кастует узел к нужному типу с отображением всех соответствующих переменных.

Пока у этого расширения 2 фичи:

  1. Приводит наследуемые от Node * переменные к нужному типу и отображает

  2. Дампит переменную-узел в stdout с помощью вызова pprint

Призываю неравнодушных принять участие в его разработке.

Вот ссылка на само расширение.

Теги:
Всего голосов 2: ↑2 и ↓0+4
Комментарии0

Состоялся релиз системной библиотеки GNU C Library (glibc) 2.40, которая полностью следует требованиям стандартов ISO C11 и POSIX.1-2017. В состав нового выпуска проекта включены исправления от 68 разработчиков.

Улучшения в Glibc 2.40

  • в заголовочный файл math.h добавлены новые экспоненциальные и логарифмические функции, определённые в стандарте C23;

  • добавлен макрос _ISOC23_SOURCE, определяющий использование возможностей, предложенных в стандарте C23 (в настоящее время в Glibc реализованы лишь часть возможностей C23);

  • добавлена настройка "glibc.rtld.enable_secure", позволяющая при проведении тестирования запускать программу так, как если бы она имела флаг смены идентификатора пользователя (setuid);

  • на платформе Linux заголовочный файл epoll.h обновлён для поддержки новых ioctl и структур epoll, появившихся в ядре Linux 6.9;

  • функциональность для выявления возможных переполнений буфера и связанных с безопасностью ошибок во время выполнения функций работы со строками и управления памятью ("_FORTIFY_SOURCE") адаптирована для сборки Glibc при помощи компилятора Clang;

  • поля с эпохальным счётчиком времени в структурах lastlog, utmp и utmpx переведены с использования 32-разрядного знакового типа на беззнаковый тип, что позволяет продлить максимальное адресуемое счётчиком время с 2038 года до 2106 года.

Источник: OpenNET.

Теги:
Всего голосов 1: ↑1 и ↓0+3
Комментарии0
Теги:
Всего голосов 4: ↑4 и ↓0+5
Комментарии1

В стандартной C-библиотеке Glibc выявлена уязвимость (CVE-2024-2961), приводящая к переполнению буфера при преобразовании специально оформленных строк в кодировке ISO-2022-CN-EXT функцией iconv().

Выявивший проблему исследователь 10 мая выступит на конференции OffensiveCon с докладом, в анонсе которого упоминается возможность эксплуатации уязвимости через приложения на языке PHP. Проблема затрагивает всю экосистему PHP и некоторые приложения.

При преобразовании строк в кодировке UCS4, в соответствии с требованиями RFC 1922, библиотека Glibc добавляет некоторые escape-символы, выделяющие части строки, в которых кодировка была изменена.

Уязвимость в вызвана некорректной проверкой границ внутренних буферов функцией iconv(), что может привести к переполнению буфера максимум на 4 байта. При переполнении за границу буфера могут быть записаны определённые фиксированные значения, такие как '$+I', '$+J', '$+K', '$+L', '$+M' и '$*H'. Несмотря на то, что эксплуатация подобной уязвимости для выполнения кода кажется маловероятной, этого оказалось достаточно для подготовки нескольких прототипов эксплоитов для удалённой атаки на PHP-приложения, приводящей к выполнению кода.

Уязвимость проявляется с 2000 года и устранена в находящейся в разработке ветке Glibc 2.40. Исправление также доступно в виде патчей для выпусков Glibc с 2.32 по 2.39. В дистрибутивах проследить за исправлением уязвимости можно на страницах: Debian, Ubuntu, Gentoo, RHEL, SUSE, Fedora, Arch.

Источник: OpenNET.

Теги:
Всего голосов 4: ↑4 и ↓0+6
Комментарии1

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

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

#include <dlfcn.h>
#include <stdio.h>

struct leaksaver {
        struct leaksaver *next;
        void *pointer;
} *bigbucket;

void *
malloc(size_t len)
{
        static void *(*nextmalloc)(size_t);
        nextmalloc = dlsym(RTLD_NEXT, "malloc");
        void *ptr = nextmalloc(len);
        if (ptr) {
                struct leaksaver *saver = nextmalloc(sizeof(*saver));
                saver->pointer = ptr;
                saver->next = bigbucket;
                bigbucket = saver;
        }
        return ptr;

Пояснение автора кода в оригинале:

Every allocated pointer is saved in the big bucket, where it remains accessible. Even if no other references to the pointer exist in the program, the pointer has not leaked.

It is now entirely optional to call free. If you don’t call free, memory usage will increase over time, but technically, it’s not a leak. As an optimization, you may choose to call free to reduce memory, but again, strictly optional.

Problem sovled!

Теги:
Всего голосов 6: ↑3 и ↓30
Комментарии7
1

Вклад авторов