Dmitry Develop
ссылка на канал | ссылка на группу
Сегодня я открыл для себя новый инструмент, который делает сгенерированный компилятором ассемблерный код более читаемым.
Если вы когда-нибудь смотрели преобразованный С++ код в ассемблерный код или видели сообщение об ошибке "
И чем длиннее название символа, больше количество аргументов и сложнее принимаемые и возвращаемый типы данных, тем страшнее и непонятнее будет итоговое название.
Этот механизм называется
Он нужен для того, чтобы компоновщик (
Чтобы преобразовать
При запуске программа будет ожидать текст в потоке ввода и выводить в консоль преобразованный текст.
Так как она не умеет работать с файлами напрямую, нужно перенаправить поток ввода и вывода:
Это работает так:
Запускается программа
Предыдущую конструкцию вообще можно объединить в одну строчку с генерацией ассемблерного кода:
Как объединить несколько команд и перенаправить ввод-вывод в вашем терминале и операционной системе ищите самостоятельно:
"
"
Более сложный пример:
ссылка на канал | ссылка на группу
Если вы когда-нибудь смотрели преобразованный С++ код в ассемблерный код или видели сообщение об ошибке "
undefined reference to _Z7timeNowPx", вы могли заметить, что привычное название функции, например, timeNow(uint64*) превращается в _Z7timeNowPx.И чем длиннее название символа, больше количество аргументов и сложнее принимаемые и возвращаемый типы данных, тем страшнее и непонятнее будет итоговое название.
Этот механизм называется
name mangling.Он нужен для того, чтобы компоновщик (
linker) мог различать символы с одинаковыми названиями, перегрузки функций и не только, создавая для каждого символа уникальное неповторяющееся название.Чтобы преобразовать
mangled символы в читаемый вид, нужна программа c++filt.exe, которая поставляется вместе с компилятором gcc.При запуске программа будет ожидать текст в потоке ввода и выводить в консоль преобразованный текст.
Так как она не умеет работать с файлами напрямую, нужно перенаправить поток ввода и вывода:
c++filt.exe < mangled.asm > demangled.asmЭто работает так:
Запускается программа
c++filt.exe, в поток ввода передаётся содержимое файла mangled.asm и потом вывод программы перенаправляется в файл demangled.asm.Предыдущую конструкцию вообще можно объединить в одну строчку с генерацией ассемблерного кода:
g++.exe -S -masm=intel -fverbose-asm -o mangled.asm main.cpp && c++filt.exe < mangled.asm > demangled.asmКак объединить несколько команд и перенаправить ввод-вывод в вашем терминале и операционной системе ищите самостоятельно:
"
chain commands in terminal""
terminal redirect input output"Более сложный пример:
_ZNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEE15_M_replace_coldEPcyPKcyystd::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::_M_replace_cold(char*, unsigned long long, char const*, unsigned long long, unsigned long long)ссылка на канал | ссылка на группу
🔥2🤯1
Раньше здесь был ъуъ).
...
Недавно я делал лабораторную работу, в которой надо было в runtime создавать одно- и многомерные массивы (1D, 2D, 3D) большого размера, заполнять их: последовательными значениями по возрастанию, по убыванию и перемешанными значениями (shuffle), а потом применять к ним различные алгоритмы сортировки.
Так как код хотелось сделать как можно проще и универсальнее, для начала я решил определиться каким образом я буду выделять, передавать и индексировать массив.
Способов передачи массивов в функцию довольно много: от написания шаблонной функции до передачи типа
У каждого способа были свои преимущества и недостатки: один был сложным, второй подходил только для массивов фиксированного размера, третий вообще активно использовал UB (но я не уверен).
Потом я вспомнил, что в Си / С++ массивы в памяти хранятся построчно (row-major order):
Многомерный массив привести к одномерному и соответственно вычислить индекс:
Поэтому я решил, что массив от 1 до 3 измерений (можно и больше), я буду выделять так:
Заметьте, что, в привычном виде для разработчиков игр и графики, оси вектора (размерности) перечисляются в таком порядке:
А единичные векторы, из суммы которых можно представить любой вектор, в таком:
Но в C++ размерности надо указывать задом наперёд.
В итоге, чтобы передать такой flatten массив в функцию достаточно будет:
Можно было создавать не двумерный массив, а массив указателей на одномерные массивы.
Но это сложнее: надо создавать сначала массив указателей, потом через цикл создавать массив строк и удалять соответственно в обратном порядке.
Такой массив можно передавать в функцию, как
Но как дело доходит до трёхмерного... оно того не стоит.
Да и универсальный алгоритм сложнее написать, если вовсе невозможно.
ссылка на канал | ссылка на группу
...
Недавно я делал лабораторную работу, в которой надо было в runtime создавать одно- и многомерные массивы (1D, 2D, 3D) большого размера, заполнять их: последовательными значениями по возрастанию, по убыванию и перемешанными значениями (shuffle), а потом применять к ним различные алгоритмы сортировки.
Так как код хотелось сделать как можно проще и универсальнее, для начала я решил определиться каким образом я буду выделять, передавать и индексировать массив.
Способов передачи массивов в функцию довольно много: от написания шаблонной функции до передачи типа
int (*row)[10].У каждого способа были свои преимущества и недостатки: один был сложным, второй подходил только для массивов фиксированного размера, третий вообще активно использовал UB (но я не уверен).
Потом я вспомнил, что в Си / С++ массивы в памяти хранятся построчно (row-major order):
// многомерный массив
int array[3][2][3]
{
{
{
{ 1, 2, 3 }
},
{
{ 4, 5, 6 }
}
},
{
{
{ 7, 8, 9 }
},
{
{ 10, 11, 12 }
}
}
{
{
{ 13, 14, 15 }
},
{
{ 16, 17, 18 }
}
},
};
// представление в памяти
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
Многомерный массив привести к одномерному и соответственно вычислить индекс:
// было:
array[k][j][i]
// стало:
array[k*Y*X + j*X + i]
Поэтому я решил, что массив от 1 до 3 измерений (можно и больше), я буду выделять так:
// было:
new int[z][y][x] { };
// стало:
new int[z * y * x] { };
Заметьте, что, в привычном виде для разработчиков игр и графики, оси вектора (размерности) перечисляются в таком порядке:
x, y, z.А единичные векторы, из суммы которых можно представить любой вектор, в таком:
i, j, k.Но в C++ размерности надо указывать задом наперёд.
В итоге, чтобы передать такой flatten массив в функцию достаточно будет:
void arrayModify(int* array, const int x, const int y = 1, const int z = 1);
Можно было создавать не двумерный массив, а массив указателей на одномерные массивы.
Но это сложнее: надо создавать сначала массив указателей, потом через цикл создавать массив строк и удалять соответственно в обратном порядке.
Такой массив можно передавать в функцию, как
int** array.Но как дело доходит до трёхмерного... оно того не стоит.
Да и универсальный алгоритм сложнее написать, если вовсе невозможно.
ссылка на канал | ссылка на группу
👍3🕊1
Я заметил, что в последнее время я в основном пишу всё в группу, но не в канал.
Хотя канал был создан, чтобы делиться с другими чем-то по тематике около С++, электроники и техники.
Ну, а ещё чтобы не доставать своих друзей и близких часовыми лекциями по поводу языка С++ и моих проектов)).
Думаю, причина в том, что я слишком сильно завысил критерии к качеству и к тематике поста.
А ещё как-то не хочется по каждому пустяку делать пост в канале.
Что думаете, я из пустяка сделал себе проблему?
И стоит просто забить и выкладывать почти всё в канал после вычитки и всех правок?
ссылка на канал | ссылка на группу
Хотя канал был создан, чтобы делиться с другими чем-то по тематике около С++, электроники и техники.
Ну, а ещё чтобы не доставать своих друзей и близких часовыми лекциями по поводу языка С++ и моих проектов)).
Думаю, причина в том, что я слишком сильно завысил критерии к качеству и к тематике поста.
А ещё как-то не хочется по каждому пустяку делать пост в канале.
Что думаете, я из пустяка сделал себе проблему?
И стоит просто забить и выкладывать почти всё в канал после вычитки и всех правок?
ссылка на канал | ссылка на группу
Что ж, предыдущее случайное недоразумение я переписал:
https://t.me/a248640develop/155
ссылка на канал | ссылка на группу
https://t.me/a248640develop/155
ссылка на канал | ссылка на группу
Dmitry Develop
projectHierarchy.png
Переделываю с нуля шаблон проекта на C++ для vs code.
Дело дошло до настроек внешнего оформления и создания иерархии проекта.
Хочется в шаблоне проекта указать ключи компилятора для подключения какой-нибудь самописной или сторонней библиотеки.
Вопрос в том, какую иерархию проекта сделать?
Сделать папку library и туда класть скомпилированные библиотеки, но куда класть header файлы?
Не хотелось бы перемешивать файлы проекта с файлами библиотеки.
Может, разбить проект как бы контейнеры, где у каждого контейнера есть свои исходные и заголовочные файлы?
ссылка на канал | ссылка на группу
Дело дошло до настроек внешнего оформления и создания иерархии проекта.
Хочется в шаблоне проекта указать ключи компилятора для подключения какой-нибудь самописной или сторонней библиотеки.
Вопрос в том, какую иерархию проекта сделать?
Сделать папку library и туда класть скомпилированные библиотеки, но куда класть header файлы?
Не хотелось бы перемешивать файлы проекта с файлами библиотеки.
Может, разбить проект как бы контейнеры, где у каждого контейнера есть свои исходные и заголовочные файлы?
project| main| | source| | | *.cpp| | include| | | *.hpp| library1| | source| | | *.cpp| | include| | | *.hpp| library2| | source| | | *.cpp| | include| | | *.hppссылка на канал | ссылка на группу
Dmitry Develop
IMG_20231213_213456.jpg
Как же мне нравится качество китайских товаров.
Подключил я сейчас гирлянду: всё светится, красиво.
А через минуту: хлопок, вспышка, запах гари, чёрный дым идёт из коробочки-контроллера, она перестала работать.
Первым делом я подумал, что в поломке гирлянды виноват сетевой фильтр, который я недавно паял.
Разобрал коробочку, от туда продолжает идти чёрный дым, пахнет чем-то горелым.
Четверть площади платы покрылась копотью.
Я даже и не заметил сразу, что отгорели два провода сетевой вилки.
Зачистил провода, встал на резиновый коврик, вставил вилку в розетку и аккуратно коснулся оголёнными проводами контактов на плате...
Ничего не заискрилось, не хлопнуло, не сгорело и гирлянда засветилась.
При таком сечении провода, без нормального лужения и фиксации провода я не удивлён, что это произошло.
Видимо, пайка провода оказалась самым слабым звеном цепи и поэтому отгорела.
А почему это произошло даже не знаю, наверное, один из сетевых проводов отвалился и что-то замкнул.
Сегодня обойдусь без сложных ремонтов и выбрасывания в мусорку).
ссылка на канал | ссылка на группу
Подключил я сейчас гирлянду: всё светится, красиво.
А через минуту: хлопок, вспышка, запах гари, чёрный дым идёт из коробочки-контроллера, она перестала работать.
Первым делом я подумал, что в поломке гирлянды виноват сетевой фильтр, который я недавно паял.
Разобрал коробочку, от туда продолжает идти чёрный дым, пахнет чем-то горелым.
Четверть площади платы покрылась копотью.
Я даже и не заметил сразу, что отгорели два провода сетевой вилки.
Зачистил провода, встал на резиновый коврик, вставил вилку в розетку и аккуратно коснулся оголёнными проводами контактов на плате...
Ничего не заискрилось, не хлопнуло, не сгорело и гирлянда засветилась.
При таком сечении провода, без нормального лужения и фиксации провода я не удивлён, что это произошло.
Видимо, пайка провода оказалась самым слабым звеном цепи и поэтому отгорела.
А почему это произошло даже не знаю, наверное, один из сетевых проводов отвалился и что-то замкнул.
Сегодня обойдусь без сложных ремонтов и выбрасывания в мусорку).
ссылка на канал | ссылка на группу
Dmitry Develop
image_2023-12-14_15-40-50.png
Можно было сделать и лучше; с параметрами, мне кажется, немного беда.
Зато у меня получилось хорошее именование функций, мне нравится что всё сделано по общему шаблону.
Есть много повторений кода, но как только я пытался вынести общий код в отдельную функцию, а сам алгоритм передавать во внутрь лямбдой, мне всё стало казаться излишним усложнением и неудобным в реализации.
ссылка на канал | ссылка на группу
Зато у меня получилось хорошее именование функций, мне нравится что всё сделано по общему шаблону.
Есть много повторений кода, но как только я пытался вынести общий код в отдельную функцию, а сам алгоритм передавать во внутрь лямбдой, мне всё стало казаться излишним усложнением и неудобным в реализации.
ссылка на канал | ссылка на группу
Dmitry Develop
ссылка на канал | ссылка на группу
Вот что происходит, когда пишешь немаленький проект без включенных предупреждений от компилятора, а потом решаешь включить их и скомпилировать ещё раз.
Просто я немного изменил иерархию проекта и решил заодно ещё и команду сборки переписать.
Надо будет уделить внимание каждому предупреждению и исправить причину его возникновения.
Количеству неиспользованных переменных я не удивлён, в проекте очень много legacy кода.
И это не самый страшный случай.
Хуже всего было только тогда, когда я свой старый игровой движок, код которого был написал под компилятор msvc несколько лет назад, попытался скомпилировать при помощи последнего g++.
Было очень много ошибок и предупреждений, и даже спустя час правок файлов по всему проекту, мне так и не удалось его скомпилировать.
ссылка на канал | ссылка на группу
Просто я немного изменил иерархию проекта и решил заодно ещё и команду сборки переписать.
Надо будет уделить внимание каждому предупреждению и исправить причину его возникновения.
Количеству неиспользованных переменных я не удивлён, в проекте очень много legacy кода.
И это не самый страшный случай.
Хуже всего было только тогда, когда я свой старый игровой движок, код которого был написал под компилятор msvc несколько лет назад, попытался скомпилировать при помощи последнего g++.
Было очень много ошибок и предупреждений, и даже спустя час правок файлов по всему проекту, мне так и не удалось его скомпилировать.
ссылка на канал | ссылка на группу
Dmitry Develop
image_2023-12-16_02-13-50.png
Что делать, если во время отладки в vs code вместо содержимого STL контейнера видна его внутренняя реализация?
На фото выше в порядке сверху вниз: сам код, вид
Надо просто в
Вообще, если разбираться подробнее как это работает, всё довольно сложно.
Похоже, перед представлением данных, gdb или адаптер использует скрипты на python.
ссылка на канал | ссылка на группу
На фото выше в порядке сверху вниз: сам код, вид
std::vector в отладчике до и после изменений. Надо просто в
launch.json добавить "setupCommands", чтобы перед запуском отладки передать в gdb один ключ:// launch.json
{
"version": "0.2.0",
"configurations":
[
{
...
"setupCommands":
[
{
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
...
}
]
}
Вообще, если разбираться подробнее как это работает, всё довольно сложно.
Похоже, перед представлением данных, gdb или адаптер использует скрипты на python.
ссылка на канал | ссылка на группу
Я всегда предпочитал сложный путь лёгкому, стандартному решению — нестандартное, поверхностному изучению — углублённое.
Благодаря этому я уже сейчас знаю или умею то, что другие узнают или научатся только в будущем.
Бывает, решение или совет нужны прямо здесь и сейчас, а времени и навыков самостоятельно разобраться нет.
Поэтому я хочу предложить свою помощь в вопросах, связанных с компилятором mingw (gcc), редактором кода vs code, написания лабораторных работ, программирования на C++, решения проблем с кодировками и другими распространёнными проблемами.
Оказывать кому-то помощь делом или советом не только интересно, но помогает мне набираться опыта и даже немного подзаработать).
Я свой уровень С++ оцениваю где-то между junior и middle: у меня довольно выборочные знания и умения: где-то поверхностные, где-то углублённые.
Поэтому каждый вопрос разбираю индивидуально и помогу, чем смогу.
Буду рад за свою помощь получить вознаграждение.
Оплату принимаю на российскую карту или в криптовалюте.
ссылка на канал | ссылка на группу
Благодаря этому я уже сейчас знаю или умею то, что другие узнают или научатся только в будущем.
Бывает, решение или совет нужны прямо здесь и сейчас, а времени и навыков самостоятельно разобраться нет.
Поэтому я хочу предложить свою помощь в вопросах, связанных с компилятором mingw (gcc), редактором кода vs code, написания лабораторных работ, программирования на C++, решения проблем с кодировками и другими распространёнными проблемами.
Оказывать кому-то помощь делом или советом не только интересно, но помогает мне набираться опыта и даже немного подзаработать).
Я свой уровень С++ оцениваю где-то между junior и middle: у меня довольно выборочные знания и умения: где-то поверхностные, где-то углублённые.
Поэтому каждый вопрос разбираю индивидуально и помогу, чем смогу.
Буду рад за свою помощь получить вознаграждение.
Оплату принимаю на российскую карту или в криптовалюте.
ссылка на канал | ссылка на группу
🤡5
В конце каждого сообщения я добавляю две ссылки: одна на текущее сообщение в канале, другая на группу.
Зачем?
Согласно статистике, все репосты были сделаны анонимно.
То есть без ссылки на канал, откуда оно было переслано, и соответственно, без кнопки комментирования.
Может, кто-то в избранное себе сохранил на всякий случай или с кем-то поделился, но без ссылки на мой канал.
А это немного, но всё же уменьшает количество просмотров потенциально заинтересованных людей.
Ещё одна причина:
Я довольно часто сразу или через несколько часов делаю правки или дополняю текст поста.
Если переслать пост не в виде ссылке, сохранится его копия на данный момент.
Актуальная же версия доступна только по ссылке.
Недавно я задумался, что делать надпись и ссылку довольно громоздко, эта конструкция отвлекает от основного содержимого.
Поэтому в последнем сообщении и в текущем я ради эксперимента сделал новый вид блока и названия ссылок.
Подскажите, какие бы сделать вид блока и названия для ссылок?
"
"
"
"
Названия, скорее всего, в будущем изменятся.
После окончательного выбора вида блока и названий для ссылок, я изменю все остальные сообщения по этому шаблону.
ссылка на канал | ссылка на группу
Зачем?
Согласно статистике, все репосты были сделаны анонимно.
То есть без ссылки на канал, откуда оно было переслано, и соответственно, без кнопки комментирования.
Может, кто-то в избранное себе сохранил на всякий случай или с кем-то поделился, но без ссылки на мой канал.
А это немного, но всё же уменьшает количество просмотров потенциально заинтересованных людей.
Ещё одна причина:
Я довольно часто сразу или через несколько часов делаю правки или дополняю текст поста.
Если переслать пост не в виде ссылке, сохранится его копия на данный момент.
Актуальная же версия доступна только по ссылке.
Недавно я задумался, что делать надпись и ссылку довольно громоздко, эта конструкция отвлекает от основного содержимого.
Поэтому в последнем сообщении и в текущем я ради эксперимента сделал новый вид блока и названия ссылок.
Подскажите, какие бы сделать вид блока и названия для ссылок?
"
канал | группа","
оригинал | обсудить","
Dmitry Develop | обсудить","
ссылка на сообщение | ссылка на обсуждение", ...Названия, скорее всего, в будущем изменятся.
После окончательного выбора вида блока и названий для ссылок, я изменю все остальные сообщения по этому шаблону.
ссылка на канал | ссылка на группу
Dmitry Develop
image_2023-12-18_01-46-05.png
Понимание, каким образом хранятся массивы в памяти и как делать одномерную адресацию многомерного массива и наоборот, позволяет некоторые задачи, данные в которых хранятся в виде одномерного массива, представлять, как многомерный массив.
Посмотрите, как выглядел код до и после изменений: это огромная разница.
Эту символьную таблицу, которая представлена одномерным массивом char с null-терминатором в конце, я представил как массив 3 на 3 ячейки и при помощи цикла сделал её заполнение.
Вывод программы (числа для примера только):
Кому не особо понятно, почитайте тут объяснение про массивы и память:
https://t.me/a248640developchat/1029
ссылка на канал | ссылка на группу
Посмотрите, как выглядел код до и после изменений: это огромная разница.
Эту символьную таблицу, которая представлена одномерным массивом char с null-терминатором в конце, я представил как массив 3 на 3 ячейки и при помощи цикла сделал её заполнение.
Вывод программы (числа для примера только):
| sorted | shuffled | unsorted bubble | 1999990 ms | 4999993 ms | 7999996 ms shaker | 2999991 ms | 5999994 ms | 8999997 msselection | 3999992 ms | 6999995 ms | 9999998 msКому не особо понятно, почитайте тут объяснение про массивы и память:
https://t.me/a248640developchat/1029
ссылка на канал | ссылка на группу
👍2
Media is too big
VIEW IN TELEGRAM
Как вам консольное меню?)
Меню многоуровневое с проверкой на корректный ввод.
Весь проект вышел в 700 строк кода.
ссылка на канал | ссылка на группу
Меню многоуровневое с проверкой на корректный ввод.
Весь проект вышел в 700 строк кода.
ссылка на канал | ссылка на группу
🔥2