LINUX.ORG.RU
ФорумTalks

Кто-то еще верит, что C/C++ не для криворуких макак?

 , ,


0

2

Поставщик корпоративных решений в сфере ИТ-безопасности, Fortinet. 40 уязвимостей, Карл, 40! Среди них stack-based buffer overflow.

https://thehackernews.com/2023/02/fortinet-issues-patches-for-40-flaws.html

Вы правда думаете, у них кодеры индийские домохозяйки, выучившиеся программированию на 6 месячных курсах?

★★★★★

Последнее исправление: cetjs2 (всего исправлений: 1)

Ответ на: комментарий от bugfixer

Спешу Вас расстроить - reference это decayed pointer, ни больше ни меньше.

Не надо меня расстраивать. Лучше бы порадовали чем-нибудь. Эта информация никак не исправляет ситуацию. Всё равно в одном случае точка, в другом - стрелочка. Если в другом языке для обращения к объектам на самом деле используются неявные указатели, то меня это мало волнует. Главное - в синтаксисе меньше отвлекающих элементов.

Я не хочу сказать, что C++ хуже других языков. Не хуже. Но если в программе широко используется полиморфизм времени выполнения, то имеет смысл обратить внимание на более подходящие языки.

Kogrom
()
Ответ на: комментарий от Kogrom

Всё равно в одном случае точка, в другом - стрелочка.

В Visual Studio можешь всегда писать точку, Visual Studio сама меняет на стрелочку когда нужно.

В gcc/clang довольно понятные сообщения об ошибке:

error: request for member 'x' in 'f', which is of pointer type 'test*' (maybe you meant to use '->' ?)
    8 |         f.x;
      |           ^
error: member reference type 'test *' is a pointer; did you mean to use '->'?
        f.x;
        ~^
         ->
fsb4000 ★★★★★
()
Ответ на: комментарий от bugfixer

На крошечный пример - крошечные проблемы. У большого примера будут большие проблемы. А так можно и без костылей переписать пример с фабричным методом, что он будет короче, понятнее и без указателей и стрелочек:

#include <iostream>
#include <vector>

using namespace std;

enum Warrior_ID { Infantryman_ID=0, Archer_ID, Horseman_ID };

class Warrior
{
    Warrior_ID m_Id;
public:
    Warrior( Warrior_ID id ):m_Id(id){}

    void info()
    {
        switch (m_Id)
        {
        case Infantryman_ID:
            cout << "Infantryman" << endl;
            break;
        case Archer_ID:
            cout << "Archer" << endl;
            break;
        case Horseman_ID:
            cout << "Horseman" << endl;
            break;
        }
    }

};

int main()
{
    vector<Warrior> warriors;
    warriors.emplace_back( Warrior( Infantryman_ID));
    warriors.emplace_back( Warrior( Archer_ID));
    warriors.emplace_back( Warrior( Horseman_ID));

    for(auto warrior: warriors)
        warrior.info();
}

Почти в 2 раза короче, а делает то же самое. Но мы же понимаем что в этом коде что-то не то, да? Потому что исходный вариант подразумевает некоторый контекст, который не можем показать из-за краткости.

Вот вы начинаете хитрить, чтобы формально нельзя было сказать, что с кучей работаем. Да, можно, например, сделать глобальный массив байтов и аллокатор к нему и использовать его вместо кучи. Формально будет не куча, конечно. А фактически - получаем почти те же проблемы, что и с кучей.

Kogrom
()
Последнее исправление: Kogrom (всего исправлений: 1)
Ответ на: комментарий от fsb4000

Да, есть простые костыли (gcc), а есть автоматизированные (Visual Studio). Но особенности синтаксиса это не меняет.

Я не говорю, что это дефект. Для низкоуровневого кода оно в самый раз. Для библиотек или маленьких программ тоже нормально. Для «языковедов» - такие тонкости проблем не доставляют. Но если ты сосредоточен на высокоуровневых потребностях пользователя в огромной программе, то тебе лишние закорючки ни к чему.

Kogrom
()
Ответ на: комментарий от Kogrom

он будет короче, понятнее и без указателей и стрелочек

Дык, это ж ведь самое главное - нет стрелочкам! Слава … Ой, что-то я, кажется, увлёкся.

в огромной программе, то тебе лишние закорючки ни к чему.

Как мило.

bugfixer ★★★★
()
Ответ на: комментарий от bugfixer

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

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

Warrior(Warrior_ID id)
{
    m_Id = id;
}

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

А emplace_back(…) и push_back(…) можно было заменить одним add(). Это уже не синтаксис, но всё равно особенности языка.

И оно всё вот такое.

Kogrom
()
Ответ на: комментарий от Kogrom

А emplace_back(…) и push_back(…) можно было заменить одним add(). Это уже не синтаксис, но всё равно особенности языка.

А весь софт, который с push_back написан типа менять и пересобирать?

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

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

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

Kogrom
()
Ответ на: комментарий от Kogrom

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

Если бы был один метод add, каждый раз надо было бы лезть в инет за справкой, а кто там чего и где конструирует, а есть ли конструктор с инициализатором, а что вот этот параметр с флагом, где он в очередности и какие флаги.

В C++ вообще не в этом проблема, а в том, что порог вхождения нереально большой, потому что полно легаси кода, который надо поддерживать, и в котором навелосипедили то, что потом появилось в стандартах 11+. И никто там ничего переписывать и менять не будет, потому что: а) работает, как швейцарские часы б) авторов уже не найти.

И вот когда в коде лапша из строк char*, std::string и еще чего-то кастомного, с кастомной библиотекой тредов, своими RPC, а кодеры уровня миддл, и учатся некоторым вещам на ходу (а других кодеров нет), и все это собирается кастомной системой сборки, которую пилили те авторы, которых уже нет и … (далее по списку), поддерживать такой код надо иметь стальные нервы и бычьи яйца, и это в итоге получается очень дорого, кстати.

А на C++20, да с новенькой Visual Studio новый проект начать особо яиц не надо.

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

Если бы был один метод add, каждый раз надо было бы лезть в инет за справкой

Во-первых, так и с emplace_back() надо за справкой лезть, чем он от push_back() отличается. Во-вторых, можно без флажков сделать что-то типа:

template <typename T>
void add(T& u)
{
    cout << "variable with name" << endl;
}

template <typename T>
void add(T&& u)
{
    cout << "temporary variable" << endl;
}

int main()
{
    int a = 10;
    add(a);
    add(5);
}

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

С легаси проблема понятная. И там больше сложностей не со стандартной библиотекой, а с какими-нибудь древними версиями библиотек типа MFC.

Kogrom
()
Ответ на: комментарий от Kogrom

так и с emplace_back() надо за справкой лезть, чем он от push_back() отличается.

Тяжко Вам будет, да. На самом деле naming там довольно консистентный.

bugfixer ★★★★
()
Ответ на: комментарий от Kogrom

ну, скажем, так. Даже я с очень слабым знанием С++ и особенно новых его фич, знаю на некотором интуитивном уровне, что всё, что содержит слово emplace в стандартной библиотеке контейнеров - это что-то связанное с оптимизацией производительности, и что во многих случаях (если не в большинстве) можно обойтись push-вариантами методов. Т.е. чтобы вот совсем не знать, откуда растут ноги emplace - это надо очень давно не быть в тренде C++, или сознательно эти тренды игнорировать.

seiken ★★★★★
() автор топика
Ответ на: комментарий от firkax

+100500

Проблема вовсе не в языке программирования, а именно вот в этом лютом говнище:

Поставщик корпоративных решений

Интересно, а кто-нибудь может назвать хотя бы одно «корпоративное решение», которое бы не было невменяемым кромешным звездецом?

Stanson ★★★★★
()
Ответ на: комментарий от bugfixer

Отвечу сразу Вам и seiken. Тяжко будет не мне. Все мои аргументы приводятся в пользу того, что даже если программист не использует хитрые шаблоны, то он не сможет на C++ писать так же, как на другом широко распространённом языке. Надо учитывать миллион мелочей.

Про нейминг. Даже если согласиться, что он хороший, то сильно отличается от других языков. Например, словарь в других языках - либо Dictionary, либо dict. В C++ - map. В других языках словарь из пар ключ-значение. В C++ - из первый-второй. А названия стандартных исключений - вообще непонятно что: domain_error, runtime_error, system_error, bad_exception…

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

Kogrom
()
Ответ на: комментарий от Kogrom

Тяжко будет не мне.

Вам, Вам - не я же здесь закатил «Плач Ярославны» заламывая руки и причитая «как всё плохо / непривычно / непонятно», причём из того что я пока вижу - на пустом месте, спешу заметить.

что даже если программист не использует хитрые шаблоны,

Неправда.

то он не сможет на C++ писать так же, как на другом широко распространённом языке.

Вполне сможет.

Надо учитывать миллион мелочей.

Это правда. Но Вы же не собирались придти поучаствовать в F1 получив права месяц назад?

Например, словарь в других языках - либо Dictionary, либо dict. В C++ - map. В других языках словарь из пар ключ-значение.

std::map<> - это btree, ни больше ни меньше. Как оно там называется в других языках - я без понятия, но вот в понимании подавляющего числа моих знакомых Dictionary - это совсем другая структура данных позволяющая быстро транслировать «тяжелые» ключи (чаще всего строки) в условные ints туда (самое большее за O(logN)) и обратно (за O(1)) и использующаяся чтобы не хранить 100500 идентичных объектов, существенно экономя при этом память.

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

bugfixer ★★★★
()
Ответ на: комментарий от bugfixer

std::map<> - это btree, ни больше ни меньше.

Если бы мы говорили о реализации, то этот аргумент был бы принят. Мы же говорили о нейминге. Ведь в C++ есть unordered_map и прочие не вошедшие в стандарт реализации hash_map. Они тоже map-ы. Соответственно map и btree совсем не синонимы.

Но Вы же не собирались придти поучаствовать в F1 получив права месяц назад?

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

Комментировать утверждения про «Плач Ярославны» и ни на чём не основанные предположении о моём опыте не виду смысла.

Kogrom
()
Ответ на: комментарий от Kogrom

Ведь в C++ есть unordered_map и прочие не вошедшие в стандарт реализации hash_map

Вы таки отстали от жизни.

и ни на чём не основанные предположения

Да ладно. Ваши утверждения и вопросы говорят сами за себя…

удобно использовать гоночную машину в повседневной жизни, получив права месяц назад.

И? Вы возможно не понимаете как оно работает и зачем вот это всё делается…

bugfixer ★★★★
()
Ответ на: комментарий от Kogrom

Нейминг - это дело привычки и вообще не проблема для человека, который в теме. Проблема только для новичка в C++ с кучей другого бекграунда. А так можно много еще терминологических факапов C++ вспомнить. Например, что class - это и тип данных, и «класс типов данных в шаблонных аргументах», что как бы вообще никак не одно и то же. В Аде эти две сущности официально называются по-разному, но это так, к слову, потому что Ада почти никому не сдалась, хоть ЯП и постройнее плюсов будет, и побезопаснее. Просто не гонится за всеми парадигмами сразу, и даже не пытается, в отличие от плюсов.

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

Например, что class - это и тип данных, и «класс типов данных в шаблонных аргументах»

в шаблонных аргументах можно писать typename.

fsb4000 ★★★★★
()
Ответ на: комментарий от fsb4000

в шаблонных аргументах можно писать typename.

да, но лень :)

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

Нейминг - это дело привычки и вообще не проблема для человека, который в теме. Проблема только для новичка в C++ с кучей другого бекграунда.

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

Когда-то я считал, что C++ - единственно верный язык. Так продолжалось до тех пор, пока мне не порекомендовали книжку Кента Бека про TDD для общего развития. А он почти сразу говорит: «Давайте напишем систему для юнит-тестирования на Питоне». И на этом месте я чуть не бросил читать книжку, потому что выбран недоязычок вместо моего любимого C++.

Но потом пересилил себя, начал разбираться. Понял, что если бы автор писал на C++, оно не только стало бы в несколько раз многословнее, но и всё обвешано макросами, что усложнило бы восприятие. А если Кент Бек себе такое позволяет, то почему я не могу?

Тут ещё надо уточнить, что при написании (да и при прочтении) книжки про TDD ещё не приняли даже C++11.

Kogrom
()

Чем больше зависимых абстракций, тем больше они пригодны лишь для создания некоторой ниши алгоритмов.

А если каждая из них имеет к тому же разные ограничения, то тогда это «настоящий» С++.

Forum0888
()
Последнее исправление: Forum0888 (всего исправлений: 3)
Ответ на: комментарий от Kogrom

@bugfixer, вы удалили вполне здравый свой комментарий. Процитирую часть из него.

Если я не могу увидеть disasm - для меня всё кончено…

Это понятная точка зрения. Хотя, возможно, она немного ограничивает использование шаблонов и макросов в C++. Могу ошибаться.

Но с другой стороны этот подход не ограничивает Вас использовать Rust, ибо он нормально дизассемблируется. Не ограничивает использовать Nim (да и вообще любой язык, транслирующийся в си). Понятно, что может не быть потребности такой. Но нет оснований их критиковать.

Kogrom
()
Ответ на: комментарий от Kogrom

И на этом месте я чуть не бросил читать книжку, потому что выбран недоязычок вместо моего любимого C++

похоже на юношеский максимализм. Другое дело, что если надо «вчера» внедрить TDD в своей команде, хочется сразу книгу «все в одном», что бы без доп. гуглежки о фреймворках тестирования в плюсах.

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

Это было для общего развития. TDD так и не прижился, а с Питоном после этого много проработал. Правда, почти всегда он был как вспомогательный язык.

Забавная с ним история была. Где-то вначале десятых надо было делать проект по машинному зрению. Я предложил использовать Питон, NumPy и CUDA. Мне сказали, что это несерьёзно и в такой связке никто никогда не будет использовать. В итоге использовали другое решение. А теперь такая связка почти что стандарт.

Kogrom
()
Ответ на: комментарий от Kogrom

МЗ - это интересная тема. Но много математики надо: эпиполярная геометрия, нелинейная оптимизация, современные статистические методы. Здесь выбор ЯП - третьестепенный вопрос.

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

но если просто вместе соединить OpenCV, PCL, и еще что-нибудь для OCR и использовать готовые рецепты, то не должно быть сложностей. Если эти рецепты дадут результат. А потом надо еще понять, оно с какой аккуратностью что распознает, за чем следит, а что теряет. Какие нужны сенсоры и освещенность сцены. Т.е. по-любому выходит, что выбор языка можно когда угодно сделать, почти на любой стадии проекта.

seiken ★★★★★
() автор топика
Ответ на: комментарий от seiken

Здесь выбор ЯП - третьестепенный вопрос.

Да. Просто интересное совпадение. Современные дата-саентисты почти что этот стек и используют.

Но много математики надо: эпиполярная геометрия, нелинейная оптимизация, современные статистические методы.

Это теоретически. Фактически определяющим является не знание хитрой математики. У нас было так:

  1. Берём кандидата наук по математике. Он что-то ваяет на классических алгоритмах. Результат приемлемый, но не идеальный.
  2. Берём дата-саентистов с нейронками. Результат хуже, а вычислительные мощности нужны на порядок больше.
  3. Берём обычного программиста, который без всяких специальных знаний математики ваяет свой «велосипед». Результат примерно как в первом случае.
  4. Меняем освещение - все три алгоритма начинают приближаться к идеалу.
Kogrom
()

Поставщик корпоративных решений в сфере ИТ-безопасности, Fortinet. 40 уязвимостей, Карл, 40! Среди них stack-based buffer overflow. ... Вы правда думаете, у них кодеры индийские домохозяйки, выучившиеся программированию на 6 месячных курсах?

Ловите растамана?

Minoru ★★★
()
Ответ на: комментарий от Kogrom

Например, словарь в других языках - либо Dictionary, либо dict. В C++ - map.

прекратите нубить. map, mapping - это математически «отображение» в переводе на великомогучий. то есть отображение нечта(множество ключей) на другое нечто(множество значений). а Dictionary - это что-то гуманитарно непонятное.

https://en.wikipedia.org/wiki/Map_(mathematics)

alysnix ★★★
()
Ответ на: комментарий от Kogrom

А он почти сразу говорит: «Давайте напишем систему для юнит-тестирования на Питоне».

питон не нужен, в нем типов нет. а программирование без типов - это уже глубокий анахронизм, ну или позорное написание скриптов к тому, что написано на с++.

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

и потом, программирование блоков отступами - это плохочитаемо и вредно.

alysnix ★★★
()
Ответ на: комментарий от alysnix

прекратите нубить… глубокий анахронизм… позорное написание скриптов…

Зачем горячиться?

в таких книжках про питон

Это книжка была совсем не про питон. Вам лучше ознакомиться с тем, кто такой Кент Бек и что такое TDD. Может в жизни пригодиться.

программирование блоков отступами - это плохочитаемо и вредно

Это всё вкусовщина.

Что касается статической и динамической типизации, то у обеих есть как плюсы, так и минусы. Да даже не в типизации обычно дело, а высокоуровневости. Можно вспомнить, например, как тут Царя троллили про блог на C++. Вроде бы этот блог так и не появился. Хотя и Царь, и C++ - необычайно круты.

Тут дело и во времени написания кода, и во времени отладки, и в «батарейках». Я как-то проводил исследования по краткости кода. К питону по лаконичности приближались только Nim и D. Возможно, Ocaml бы тоже близко был. Это всё языки со статической типизацией. Думаю, на них блог бы было удобнее писать, чем на C++. Но почему-то они так и не «взлетели».

позорное написание скриптов к тому, что написано на с++

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

Kogrom
()
Ответ на: комментарий от Kogrom

Надо не противопоставлять языки, а использовать в зависимости от ситуации.

так о чем и речь.

понятно, что математику надо дать что-то попроще, и ему не нужно знать, про распределение памяти, мультитреды, процессы, ввод вывод и проч. ему главное, чтобы его формулы считались и все. ему кроме чисел и строк и ненужно почти ничего, чтобы проверить свои формулы с++ ему учить не нужно и даже вредно.

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

alysnix ★★★
()
Ответ на: комментарий от alysnix

другое дело написание «нематемизируемых» систем, смыслом которых является не результат вычисления, а состояние и поведение

Если речь про императивное программирование, то тут уже надо противопоставлять не C++ и Python, а Assembler и Haskell. Потому что последние в чистом виде представляют императивную и функциональную парадигму. А C++ и Python реализуют смесь этих парадигм.

Кстати, широко известных высокоуровневых языков, которые бы представляли бы императивную парадигму в чистом виде я даже не припомню. Если есть возвращаемое значение, то это уже немного ФП.

Kogrom
()
Закрыто добавление комментариев для недавно зарегистрированных пользователей (со score < 50)