Я вот тоже хотел об этом написать. Больно представлять, как люди пишут компиляторы, на языках с ручным управлением памятью и без ADT. Смысла особого в этом нет, а боли добавляет. Да и сетевое ПО можно отлично писать на том же Rust, если хочется язык без GC
Смысл задачи в том, чтобы научится анализировать поведение программы. Реверсинг же не только про отключение защиты. Например, может быть нужно воспроизвести какой-нибудь проприетарный алгоритм и тут модификацией пары байтиков не обойдёшься
msvc для си лучше не использовать, так как microsoft его не обновляют. Я пытался скомпилировать код на c11 и обнаружил, что он поддерживает то ли c99, то ли ansi c89.
Я для эмбед на си ничего не писал. Но когда я писал на си для десктопа мне не сильно ООП не хватало, да и раст прекрасно без него обходится. Поэтому смысла особого не вижу такой код писать
Намного лучше префиксов, как по мне. Нельзя просто так взять и int засунуть, нужно сначала его в Seconds преобразовать. Сразу понятно становится, с какой единецей измерения ты работаешь
calloc для поля data можно один сделать: q->data = calloc (size_prio * size, sizeof (void *)); Остальные calloc нужны, потому что создаются size_prio очередей. И из первой, в которой есть элементы достаётся первый элемент.
По-хорошему размеры лучше делать не интами, а size_t. Из queue_add возвращать результат, по которому можно узнать, произошла ли ошибка. Например, можно bool возвращать. Ещё такой момент - создам я очередь, добавлю в неё элемент, тогда q->high будет равен нулю. Однако, в queue_get есть такая строчка: `uint8_t a = q->data[q->high--];, которая сразу приведёт к неверному результату. Плюс неплохо было сделать функцию для освобождения памяти, которую использует очередь
Upd: Сразу не заметил, что вы использовали двойное присваивание `q->low = q->high = size-1`
Upd 2: Очередь с приоритетом страдает от тех же ошибок, что и без приоритета. Плюс ещё парочка замечаний:
queue_get должен явно сигнализировать, что очередь пуста, а не только в консоль об этом писать.
for (int i = 0; i < size_prio; i++) {
q->data[i] = calloc (size, sizeof (uint8_t));
q->low[i] = q->high[i] = size - 1; // А если size_prio > size?
q->max[i] = size; // Тут тоже
}
Для очередей с приоритетами обычно используют другие структуры данных. Однако ваш способ тоже подходит, если приоритетов строго определённое количество. Если же оно не известно, можно использовать следующие структуры данных: двоичная куча, биномиальная куча и другие кучи.
Тут я подсказать не смогу, я на расте только пару структур данных реализовывал, после чего его несколько месяцев не трогал. Я думаю, что возможно реализовать свёртку на расте. Есть пакет, в котором трейт для функторов определяется. Думаю, можно попробовать его использовать
Спасибо за наводку на TLS. Я уверен, что проблема не в скрипте компоновщика, а в самом упаковщике, так как с данным скриптом собирается только загрузчик.
Для понимания структуры ELF есть мануал. Также про ELF'ы хорошо написано в книге Learning Linux Binary Analysis. Про скрипты компоновщика можно прочитать здесь.
Я вот тоже хотел об этом написать. Больно представлять, как люди пишут компиляторы, на языках с ручным управлением памятью и без ADT. Смысла особого в этом нет, а боли добавляет. Да и сетевое ПО можно отлично писать на том же Rust, если хочется язык без GC
Смысл задачи в том, чтобы научится анализировать поведение программы. Реверсинг же не только про отключение защиты. Например, может быть нужно воспроизвести какой-нибудь проприетарный алгоритм и тут модификацией пары байтиков не обойдёшься
Насколько я знаю, в авиации беспилотниками называют самолёты без экипажа. То, что вы описали, называется автопилотом
msvc для си лучше не использовать, так как microsoft его не обновляют. Я пытался скомпилировать код на c11 и обнаружил, что он поддерживает то ли c99, то ли ansi c89.
Я для эмбед на си ничего не писал. Но когда я писал на си для десктопа мне не сильно ООП не хватало, да и раст прекрасно без него обходится. Поэтому смысла особого не вижу такой код писать
gtk тоже на си написан и там есть такое же ООП
Намного лучше префиксов, как по мне. Нельзя просто так взять и int засунуть, нужно сначала его в Seconds преобразовать. Сразу понятно становится, с какой единецей измерения ты работаешь
calloc
для поляdata
можно один сделать:q->data = calloc (size_prio * size, sizeof (void *));
Остальныеcalloc
нужны, потому что создаются size_prio очередей. И из первой, в которой есть элементы достаётся первый элемент.По-хорошему размеры лучше делать не интами, а
size_t
. Изqueue_add
возвращать результат, по которому можно узнать, произошла ли ошибка. Например, можноbool
возвращать. Ещё такой момент - создам я очередь, добавлю в неё элемент, тогдаq->high
будет равен нулю. Однако, вqueue_get
есть такая строчка: `uint8_t a = q->data[q->high--];
, которая сразу приведёт к неверному результату. Плюс неплохо было сделать функцию для освобождения памяти, которую использует очередьUpd: Сразу не заметил, что вы использовали двойное присваивание `q->low = q->high = size-1`
Upd 2: Очередь с приоритетом страдает от тех же ошибок, что и без приоритета. Плюс ещё парочка замечаний:
queue_get
должен явно сигнализировать, что очередь пуста, а не только в консоль об этом писать.Для очередей с приоритетами обычно используют другие структуры данных. Однако ваш способ тоже подходит, если приоритетов строго определённое количество. Если же оно не известно, можно использовать следующие структуры данных: двоичная куча, биномиальная куча и другие кучи.
Тут я подсказать не смогу, я на расте только пару структур данных реализовывал, после чего его несколько месяцев не трогал. Я думаю, что возможно реализовать свёртку на расте. Есть пакет, в котором трейт для функторов определяется. Думаю, можно попробовать его использовать
Какой-то корявый перевод.
«result in» в данном случае переводится, как «приводит к». И эта ошибка по всему переводу проскакивает
https://wiki.libsdl.org/Tutorials
Ссылка номер 2 в списке - SDL2 Game Tutorials