Ответ про управление памятью в С и высокоуровневых языках
Про управление памятью в С и высокоуровневых языках.
Ребята я очень люблю С, больше половины времени, за всю свою карьеру программирования программировал (и до сих пор да) на нём.
Но не надо притворяться, что проблем нет там, где они есть.
Если вы очень хорошо научились заниматься любовью стоя и в гамаке - это значит что вы лично умеете терпеть эти неудобства за приемлемую "цену", но ребята кровать всё равно лучше.
WADS: На Python \ Java \ Haskell писать всё рано быстрее.
dikPauk: При условии, что можно использовать какие угодно фреймворки - разницы будет никакой в скорости написания, при условии, что ты хорошо знаешь Си.
WADS: Ну просто реализовать руками всю ту машинерию, что Python делает под капотом (банально управление памятью, OffsetOf, отсутстиве дженериков, отсутствие синтаксического сахара....
dikPauk: Управление памятью не такая большая проблема, как может показаться. Я бы назвал это вопросом привычки, чем больше пишешь на языке, тем больше имеешь своих шаблонов, заготовок, и прочее, которые лежат где-то посередине между библиотекой и нативом.
Тут вы лукавите, выдавая идеальный случай за общий. Вот что в реальности получается с управлением памятью (от простого к сложному):
0. Программка для лабораторки:
написал, забыл. Но это не ПО, это программка.
1.
Даже в простейшем случае вы пишите что-то типа такого:
//my_module.cpp: преобразуем массив из arr1 в arr2
struct my_type arr2[] = calloc(arr_size, sizeof(*arr2));
for (int i = 0; i < arr_size; ++i)
func(&arr1[i], &arr2[i]); /* в С move-semantic ещё не завезли
* а оптимизировать доступ к памяти (читай кэши) хочется
* мы же крутые C-шники, а не какие-то там питонисты-хаскелисты */
free(arr1);
arr1 = NULL;
Вместо такого:
-- my_module.hs : преобразуем массив из arr1 в arr2
let arr2 = map func arr1
2.
В случае совсем немного сложнее вам вдобавок, нужно 100500 правил, типа:
- Всегда проверяем входные параметры на NULL
- За выделение памяти всегда отвечает вызываемая функция
- За очистку памяти (и выставление в NULL указателя) всегда отвечает вызывающая функция.
Плюс санитайзер и линтер.
И да свой набор правил вы создали и запомнили хорошо, но открывающий вашу программу о нём слыши в первый раз и ему нужно пару недель, чтобы к нему приноровится:
- 20 минут прочитать;
- 2 часа боле-менее освоиться;
- 2 недели в дебагере, чтобы не забывать во всяких мелочах.
3.
Довольно грустный случай.
Вы видите как "удобно писать программу", но это потребует очень много сопутствующей машинерии.
Поэтому вы реализовывать свой проект не правильным, с точки зрения архитектуры образом, а так, чтобы с памятью не очень много возиться. Т.е. вы портите саму программу, чтобы прилагать усилий, как в "варианте-2", а не как в "варианте-4".
4.
Ну и когда некоторая "интегральная сложность программы" преодолевает какой-то рубеж (такие "хорошо циклические структуры данных" типа IR в компиляторах, могу рассказать), у вас реально больше половины интеллектуальных усилий (включая "думание", а не просто набивание строчек кода) уходит на поддержку С того, что в высокоуровневых языках идёт из коробки.
По итогу вы вкорячиваете в свою программу половину GC (оптимизированную под ваш случай), половину валгринда, половину thread-sanitizer, обмазываетесь модулями для асинхронного выполнения кода....
В пользу табов!
Носители языка
Источник - https://t.me/whatahell_gaming/337