Re[20]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 14:30
Оценка: :)
Здравствуйте, so5team, Вы писали:


M>>Есть варианты лучше?


S>Да. Например:

S>
S>void f(int /*some_arg*/) {
S>}
S>

S>Пока имя аргумента закоментировано, вы его не можете использовать. И не получаете никаких предупреждений от компилятора.
S>Если аргумент вам таки нужен, то вы раскоментируете его имя. Если при этом забыли поиспользовать, то компилятор вам об этом напоминает.

В прототипе одно, в реализации — другое?
А потом мне захотелось закоментировать этот фрагмент кода. Только плюсовый комент (в консоли по ssh, ага, так пишут в яндексе, например, хотя там можно извратится и использовать VS Coe по ssh), или извращения с #if 0


S>Если же в прологе функции делать так:

S>
S>int main(int argc, char ** argv) {
S>  (void)argc; // Старая школа.
S>  std::ignore = argv; // Можно и молодежно.
S>}
S>

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

Я ничего не теряю, потому что USED добавляю, когда всё уже реализовано
Ситуации, когда забыл использовать параметр — ни разу не встречал. Обычно параметры всё таки осознанно добавляются, и не используются обычно, когда есть какой-то общий интерфейс, и в его частичной реализации необходимости части параметров нет


M>>Да, не трудился. На автомате


S>О том и речь. Обилие кастов в коде -- это явный знак, что где-то что-то недодумано.


Или нет
Маньяк Робокряк колесит по городу
Re[21]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 14:39
Оценка:
Здравствуйте, Marty, Вы писали:

M>В прототипе одно, в реализации — другое?


Если вы про это:
// .hpp-файл.

void f(int some_arg);

// .cpp-файл.
void f(int /*some_arg*/) {
  ...
}

То я не понимаю в чем проблема. Компилятор интересует только реализация, какие имена аргументов в декларации ему фиолетово.

M>А потом мне захотелось закоментировать этот фрагмент кода. Только плюсовый комент (в консоли по ssh, ага, так пишут в яндексе, например, хотя там можно извратится и использовать VS Coe по ssh), или извращения с #if 0


Не устраивают комментарии вокруг имени, вообще уберите имя:
void f(int) {
  ...
}


M>Я ничего не теряю, потому что USED добавляю, когда всё уже реализовано


Ох, ё.

M>Или нет


Ох, ё-ё-ё.

А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.
Re[22]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 14:58
Оценка:
Здравствуйте, so5team, Вы писали:

S>То я не понимаю в чем проблема. Компилятор интересует только реализация, какие имена аргументов в декларации ему фиолетово.


ИМена в декларации интересуют программиста, который будет поддерживать код. Держать две разные версии одного и того же — весьма неудобно


M>>А потом мне захотелось закоментировать этот фрагмент кода. Только плюсовый комент (в консоли по ssh, ага, так пишут в яндексе, например, хотя там можно извратится и использовать VS Coe по ssh), или извращения с #if 0


S>Не устраивают комментарии вокруг имени, вообще уберите имя:

S>
S>void f(int) {
S>  ...
S>}


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



S>А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.


Ну, как я и говорил, внятных аргументов у тебя нет, только демагогия про ПДД
Маньяк Робокряк колесит по городу
Re[23]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 15:04
Оценка: +1
Здравствуйте, Marty, Вы писали:

S>>А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.


M>Ну, как я и говорил, внятных аргументов у тебя нет, только демагогия про ПДД


С моей колокольни это видно так: научить можно лишь того, что хочет научится.
Re: Сишный каст - зло?
От: andrey.desman  
Дата: 29.07.23 15:07
Оценка: +2
Здравствуйте, Marty, Вы писали:

M>В целом, плюсовыми кастами пользуюсь иногда, когда надо явно сделать какое-то нетривиальное преобразование в критичном месте, и поиск таких мест по маске "_cast<" и выдаёт немного.


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


M>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)


Зачем искать касты?
Re[24]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 15:12
Оценка:
Здравствуйте, so5team, Вы писали:

S>>>А вообще знаете что? Еблюбитесь как хотите, тормоза и правила дорожного движения же придумали трусы.


M>>Ну, как я и говорил, внятных аргументов у тебя нет, только демагогия про ПДД


S>С моей колокольни это видно так: научить можно лишь того, что хочет научится.


А я не просил меня учить, я просил внятных аргументов на тему того, что сишный каст — абсолютное зло. Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься
Маньяк Робокряк колесит по городу
Re[2]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 29.07.23 15:14
Оценка:
Здравствуйте, andrey.desman, Вы писали:

M>>В целом, плюсовыми кастами пользуюсь иногда, когда надо явно сделать какое-то нетривиальное преобразование в критичном месте, и поиск таких мест по маске "_cast<" и выдаёт немного.


AD>Для указателей использую плюсовые касты, для арифметики конструкторы.

AD>Сишные касты для указателнй слишком жестоки, а для арифметических типов многовато скобок получается — он вам не Лисп!

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


M>>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)


AD>Зачем искать касты?


Ну, я не знаю, любители плюсовых кастов говорят, что их искать проще
Маньяк Робокряк колесит по городу
Re[25]: Сишный каст - зло?
От: DiPaolo Россия  
Дата: 29.07.23 15:15
Оценка: +1
M>А я не просил меня учить, я просил внятных аргументов на тему того, что сишный каст — абсолютное зло. Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься

Да нет же: сишный каст — это НЕ абсолютное зло. И имеет право на существование. Но так как в плюсах итак дохрена мест, в которых можно отстрелить себе ноги, лучше сводить риски к минимуму. Опять же: это всего лишь рекомендации, дальше уж каждый делает как считает нужным.
Патриот здравого смысла
Re[25]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 15:32
Оценка:
Здравствуйте, Marty, Вы писали:

M>А я не просил меня учить


Усвоение новой информации это уже не учеба? Ну ОК, как уже было сказано, любитесь как хотите.

M>Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься


Если вы не заметили, я здесь один из двух человек (второй DiPaolo), который хоть что-то приводит в подтверждение своих слов и единственный, который делает это на конкретных примерах. Если это "предоставлять не хочет", то... Любитесь как хотите, опять же.

И кстати, на счет "предоставлять не хочешь": http://rsdn.org/forum/cpp/8570520.1
Автор: Marty
Дата: 29.07.23

Хотелось бы увидеть ответ на простой вопрос.
Re[2]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 29.07.23 15:35
Оценка:
Здравствуйте, andrey.desman, Вы писали:

M>>Да, для удобства поиска использую именно сишный каст, а не constructor style cast вида int(...)


AD>Зачем искать касты?


Ну как же. Вот будет в интернете кто-то неправ не поверит тов.Marty, что приходится снимать константность с указателя. А ты такой "Хоп!" и простым grep-ом по исходникам обнаруживаешь места, где const_cast используется. Ну красота же!
Re: Сишный каст - зло?
От: CRT  
Дата: 29.07.23 19:14
Оценка:
Здравствуйте, Marty, Вы писали:

M>Или битовые операторы и операторы сдвига — они, как оказалось, возвращают int/int64, а не тот тип, который изначально участвует в выражении. Полечил сишными кастами.


Про целочисленное расширение (integral promotion) почитай
Re[6]: Сишный каст - зло?
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 30.07.23 01:07
Оценка:
Здравствуйте, so5team, Вы писали:

S>У меня нет под рукой собственной ошибки (хотя компилятор несколько раз в год бьет по рукам в попытках неправильно использовать static_cast, особенно в обобщенном коде). Но вот хороший пример из Интернета:

Добавь reinterpret_cast
Sic luceat lux!
Re: Сишный каст - зло?
От: rg45 СССР  
Дата: 30.07.23 07:01
Оценка: 2 (1) +3
Здравствуйте, Marty, Вы писали:

M>Почему сишным кастом пользоваться плохо?


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

M>Например, я убираю возможную знаковость у char переменной и конвертирую её в unsigned как-то так:

M>
M>auto u = (unsigned)(std::uint8_t)ch;
M>


M>Но можно и так:

M>
M>auto u = static_cast<unsigned>(static_cast<std::uint8_t>(ch));
M>


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


Я могу преложить тебе компромиссный вариант — functional-style cast expression, почитать можно здесь: https://en.cppreference.com/w/cpp/language/explicit_cast

auto u = unsigned(std::uint8_t(ch));


Для простых типов такое преобразование эквивалентно C-style cast, но, на мой взгляд, обладает несколькими преимуществами:
1) его невозможно ПО ОШИБКЕ применить к ссылке, указателю или какому-то еще типу, состоящему из двух и более лексем
2) для объектов классов такая запись будет означать инициализацию через конструктор
3) как по мне, у этой записи более приятный вид как по сравнению с C-cast, так и по сравнению с C++-cast записями

Впрочем, все сказанное — это мое имхо, на истину в последней инстанции не претендую.
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[25]: Сишный каст - зло?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 30.07.23 07:58
Оценка: +1
Здравствуйте, Marty, Вы писали:

M>А я не просил меня учить, я просил внятных аргументов на тему того, что сишный каст — абсолютное зло. Ты их предоставлять не хочешь, всё время на ПДД съехать пытаешься


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

Сишные касты 1) заменяются на плюсовые без проблем, и в ~90% случаев каждый — одним кастом. 2) Грепабельны. Этого достаточно, чтобы форсировать их применение для большинства случаев.

Ну и, естественно, нужен какой-то механизм оставлять сишные с явной пометкой "Here be dragons", как же без этого. Но полиси типа "допускать такое только когда убедишь коллегу-ревьюера" вполне эффективно.
The God is real, unless declared integer.
Re[20]: Сишный каст - зло?
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 30.07.23 08:02
Оценка: +1
Здравствуйте, so5team, Вы писали:

S>О том и речь. Обилие кастов в коде -- это явный знак, что где-то что-то недодумано.


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

Кстати, тут значительно интереснее случаи _скрытого_ каста который вообще фиг отследишь без спецмер, например:

char *strchr(const char *s, int c);


тут надо или человеку следить за присвоением результата указателю на const, или анализатор учить специфике именно таких функций...
The God is real, unless declared integer.
Re[21]: Сишный каст - зло?
От: so5team https://stiffstream.com
Дата: 30.07.23 09:02
Оценка: +1
Здравствуйте, netch80, Вы писали:

S>>О том и речь. Обилие кастов в коде -- это явный знак, что где-то что-то недодумано.


N>Только в куче случаев это недодумка самого языка. Начиная с обсуждённых тут плясок вокруг размерности и знаковости типов.


Я так понимаю, что аргумент защитников Си-шных кастов состоит в том, что когда приходится делать касты (как из-за недодумок языка, так и по другим причинам), то Си-шный каст может быть предпочтительным из-за того, что писать нужно меньше, чем при использовании static_cast/const_cast/reinterpret_cast. И вот с этим я не согласен в том плане, что язык уже предоставляет инструменты для уменьшения синтаксического оверхэда. И если даже касты мы вынуждены применять из-за недодумок языка, то у нас есть возможности написать код так, чтобы совсем уж ужасно он не выглядел.
Re: Сишный каст - зло?
От: _NN_ www.nemerleweb.com
Дата: 30.07.23 10:45
Оценка: +1
Здравствуйте, Marty, Вы писали:

У приведения в стиле abc_cast<Type> есть преимущество в однородности синтаксиса с пользовательскими приведениями типов.
Например pointer_cast
Автор: _nn_
Дата: 28.04.06
.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[2]: Сишный каст - зло?
От: Marty Пират https://www.youtube.com/channel/UChp5PpQ6T4-93HbNF-8vSYg
Дата: 30.07.23 10:56
Оценка:
Здравствуйте, _NN_, Вы писали:

_NN>У приведения в стиле abc_cast<Type> есть преимущество в однородности синтаксиса с пользовательскими приведениями типов.

_NN>Например pointer_cast
Автор: _nn_
Дата: 28.04.06
.


Это чем же C-style или constructor style касты неоднородны в синтаксисе с пользовательскими приведениями типов?
Маньяк Робокряк колесит по городу
Re[3]: Сишный каст - зло?
От: _NN_ www.nemerleweb.com
Дата: 30.07.23 14:23
Оценка:
Здравствуйте, Marty, Вы писали:

M>Здравствуйте, _NN_, Вы писали:


_NN>>У приведения в стиле abc_cast<Type> есть преимущество в однородности синтаксиса с пользовательскими приведениями типов.

_NN>>Например pointer_cast
Автор: _nn_
Дата: 28.04.06
.


M>Это чем же C-style или constructor style касты неоднородны в синтаксисе с пользовательскими приведениями типов?


Тем, что нельзя «перегрузить» для примитивных типов.
К примеру lexical_cast<int> , pointer_cast<int*> .
Как это сделать в стиле конструктора ?

Можно конечно через промежуточный объект и операцию преобразования:
PointerCast<int*>(ptr) с каким-нибудь operator int*().
Но тут у нас лишние сущности получаются.
http://rsdn.nemerleweb.com
http://nemerleweb.com
Re[16]: Сишный каст - зло?
От: B0FEE664  
Дата: 31.07.23 10:36
Оценка: :)
Здравствуйте, so5team, Вы писали:

BFE>>Рад, что вы ждёте конструктивной критики.

S>Для конструктивной нужно, чтобы критик понимал предмет разговора. Так что нет, не жду.
Т.е. вы думаете, что ваш код никто не поймёт?

BFE>>Похоже, что image_bytes объявлен как указатель на const, если это так — то это зачем?

S>Да, это const std::byte*, приходящий извне.
Но зачем нарушать контракт про "const"?

BFE>>Почему обращение к fresh_frame->data по индексу, а не по итератору?

S>Потому что это Си-ный массив. Имитировать итераторы через вызовы std::begin/end не вижу смысла.
Почему "эмитировать"? То, что в данном случае итератор — это указатель, ничего не меняет.

BFE>>Где assert(std::size(fresh_frame->data) == std::size(data_plane_sizes))?

S>Во-первых, assert-ы -- это развлечение для тех, кто нуждается в песочнице под названием debug mode. В release они не работают, поэтому для меня они бесполезны.
Это дело вкуса. То, что assert-ы не работают в release — опасное заблуждение.

S>Во-вторых, это гарантируется в принципе Upd: гарантируется, что (std::size(fresh_frame->data) >= std::size(data_plane_sizes)). By design, так сказать.

Если By design, то где static_assert?

BFE>>Зачем столько вызовов ptr_cast? Не проще ли завести один указатель?

S>Потому что исходный указатель, image_bytes, постоянно изменяется (это даже в приведенном кусочке видно). А по ходу дела его приходится приводить к std::uint8_t* (да, без const, такова специфика используемой внешней библиотеки). Можно было бы, конечно, вести сразу два указателя, image_bytes и второй, который имеет тип std::uint8_t. Но какой смысл дублировать одно и то же?
Чтобы не полагаться на оптимизатор.

BFE>>Уверены, что []( void *, std::uint8_t * ) -> void {} не ведёт к утечке памяти? (>24 байта за вызов)

S>Мне сложно представить откуда здесь может взяться утечка, т.к. этот фрагмент -- это получение указателя на функцию, которая ничего не делает. Данный указатель требуется для av_buffer_create в качестве "деаллокатора".
А то я не вижу!

S>Но т.к. деаллокатор здесь не нужен, то и функция пуста.

Вот и хотелось бы понять почему деаллокатор не нужен.
Вот в этой строчке заказ памяти AVBuffer *buf = av_mallocz(sizeof(*buf));:
 AVBufferRef *av_buffer_create(uint8_t *data, size_t size,
                               void (*free)(void *opaque, uint8_t *data),
                               void *opaque, int flags)
 {
     AVBufferRef *ret;
     AVBuffer *buf = av_mallocz(sizeof(*buf)); // тут заказали память под AVBuffer 
     if (!buf)
         return NULL;
  
     ret = buffer_create(buf, data, size, free, opaque, flags);
     if (!ret) {
         av_free(buf);
         return NULL;
     }
     return ret;
 }


смотрим дальше:
 static AVBufferRef *buffer_create(AVBuffer *buf, uint8_t *data, size_t size,
                                   void (*free)(void *opaque, uint8_t *data),
                                   void *opaque, int flags)
 {
     AVBufferRef *ref = NULL;
  
     buf->data     = data;
     buf->size     = size;
     buf->free     = free ? free : av_buffer_default_free; // т.к. free не NULL, то она будет использована вместо av_buffer_default_free
     buf->opaque   = opaque;
  
     atomic_init(&buf->refcount, 1);// очевидно подсчёт числа "ссылок", т.о. ниже идёт имитация intrusive смарт указателя
  
     buf->flags = flags;
  
     ref = av_mallocz(sizeof(*ref)); // заказали память под "ссылку"
     if (!ref)
         return NULL;
  
     ref->buffer = buf;  // в "ссылку" положили указатель на объект AVBuffer. это, впрочем, не важно.
     ref->data   = data;
     ref->size   = size;
  
     return ref;
 }

Таким образом в av_mallocz заказывается память под объект типа AVBufferRef, но вот освобождения этой памяти нет. Следовательно: либо это утечка памяти, либо вы как-то подменили av_mallocz, но если посмотреть:
 void *av_mallocz(size_t size)
 {
     void *ptr = av_malloc(size);
     if (ptr)
         memset(ptr, 0, size);
     return ptr;
 }

и
  av_malloc
void *av_malloc(size_t size)
 {
     void *ptr = NULL;
  
     if (size > atomic_load_explicit(&max_alloc_size, memory_order_relaxed))
         return NULL;
  
 #if HAVE_POSIX_MEMALIGN
     if (size) //OS X on SDK 10.6 has a broken posix_memalign implementation
     if (posix_memalign(&ptr, ALIGN, size))
         ptr = NULL;
 #elif HAVE_ALIGNED_MALLOC
     ptr = _aligned_malloc(size, ALIGN);
 #elif HAVE_MEMALIGN
 #ifndef __DJGPP__
     ptr = memalign(ALIGN, size);
 #else
     ptr = memalign(size, ALIGN);
 #endif
     /* Why 64?
      * Indeed, we should align it:
      *   on  4 for 386
      *   on 16 for 486
      *   on 32 for 586, PPro - K6-III
      *   on 64 for K7 (maybe for P3 too).
      * Because L1 and L2 caches are aligned on those values.
      * But I don't want to code such logic here!
      */
     /* Why 32?
      * For AVX ASM. SSE / NEON needs only 16.
      * Why not larger? Because I did not see a difference in benchmarks ...
      */
     /* benchmarks with P3
      * memalign(64) + 1          3071, 3051, 3032
      * memalign(64) + 2          3051, 3032, 3041
      * memalign(64) + 4          2911, 2896, 2915
      * memalign(64) + 8          2545, 2554, 2550
      * memalign(64) + 16         2543, 2572, 2563
      * memalign(64) + 32         2546, 2545, 2571
      * memalign(64) + 64         2570, 2533, 2558
      *
      * BTW, malloc seems to do 8-byte alignment by default here.
      */
 #else
     ptr = malloc(size);
 #endif
     if(!ptr && !size) {
         size = 1;
         ptr= av_malloc(1);
     }
 #if CONFIG_MEMORY_POISONING
     if (ptr)
         memset(ptr, FF_MEMORY_POISON, size);
 #endif
     return ptr;
 }

то я не вижу как, можно было бы подменить заказ памяти.
Таким образом: вы всё ещё уверены, что здесь нет утечки памяти?
И каждый день — без права на ошибку...
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.