LINUX.ORG.RU

юнионы в C++

 


2

4

Пишу телегу против плюсов. В связи с этим вопрос - насколько широко в плюсах используются нуль-терминированные строки, юнионы, неумные указатели и всё такое плохое, что делает Си опасным языком.

Даже интересует не столько то, насколько они используются в существующих программах, а есть ли примеры программ, где хорошие средства плюсов сконсолидировались и поставили заслон от опасных конструкций Си, позволив полностью избежать их использования и избавиться от типичных ошибок Си. Можно ли так написать что-то существенно сложное? Сделано ли это в любимых библиотеках (Буст, QT и иже с ними)? Вторая часть вопроса - это неопределённое поведение. В Си его много. Это подаётся как фича, но с точки зрения безопасности это дыра. Меньше ли неопределённого поведения в С++?

Есть две полярные точки зрения на вопрос:

а) С++ перекрывает Си, поэтому там всё сделано по-другому, поэтому безопасность выше б) С++ - наследник Си и в целом наследует его недостатки.

Поскольку я мало пишу на Си и ещё меньше на Си++, у меня нет сложившегося мнения на эту тему. А у ЛОРа наверняка есть мнение, даже несколько.

★★★★★

Последнее исправление: xaizek (всего исправлений: 4)
Ответ на: комментарий от byko3y

Внезапно, у C++ до сих пор есть широко используемый стандарт C++11, в котором copnst и constexpr имеют значение, несколько отличное от C++14.

Да хоть C++98. Привлечение исходников cfront 1.0 к разговору о константности в C++ не имеет смысла, т.к. эта самая константность, о которой идет речь, появилась сильно позже cfront 1.0.

Да. хорошо, сделали. Теперь как его скормить функции, у которой сигнатурка аргумента list<char *>?

Во-первых, какое отношение функция, получающая list<char*>, имеет к описанию ситуации, подробности которой я у вас на протяжении многих дней пытаюсь вытащить?

А именно:

Ваше описание (из которого ничего не понятно):

Связанный список константных значений. Удалили константу из списка — поменяли ссылки на соседних узлах. Собственно, большинство контейнеров STL испытывают большие трудности в хранении константых значений

Мой уточняющий вопрос, на который вы пока не ответили:

Если у вас интрузивный список константных значений (т.е. ссылки на соседние элементы внутри этих самых константных значениях), то как вы его вообще модифицировать собрались, а, болезный фантазер? У вас же константы.

Во-вторых, у вас проблема не с list, у вас проблема с char * и const char *. И ее можно проиллюстрировать гораздо более простым примером:

void f(char * str) { (void)str; }

void g() {
    char a[]{"Hello"};
    f(a); // (1)
    const char * b = "World";
    f(b); // (2)
}

В точке (2) вы не можете сделать вызов f, т.к. у вас b имеет тип const char *.

И совершенно фиолетово, меняет ли f содержимое str или нет.

Более того, если вы снимите с b константность, например, через C-шное приведение типа или const_cast, то вы не решите свою проблему, а только посадите в код UB.

Так что ваша проблема не в list-е и не нужно надувать щеки и загонять откровенную херню про интрузивные списки и другую подобную шнягу.

Выхода два: копировать объект в рантайме или копипастить функцию.

Вы забываете и про еще, как минимум, один вариант. Ваша функция, которая ждет list<T> может получать не list и даже не какой-то другой тип контейнера. А пару итераторов (или объект-рендж).

Тем самым вы абстрагируете свою функцию от деталей того, что именно ей требуется обрабатывать (list, vector, stack или еще что-то).

Но для такого решения нужно уметь декомпозировать.

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

Шланг тоже жалуется даже без флагов

$ clang++ 1.cpp -std=c++20
1.cpp:7:28: warning: object backing the pointer will be destroyed at the end of the full-expression [-Wdangling-gsl]
            std::string_view sv = s + "World\n";

только ГЦЦ почему-то не даёт ворнингов.

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

Вот я уже давно нацарапал пример:

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

Новых примеров не будет, правильно.

Ожидаемо. Говорить предметно – это же не щеки надувать рассказами о том, как оно в сложных-то системах.

Чтобы правильно описать, например, возврат ссылки на поле объекта-аргумент, нужно обрабатывать const/non-const, value/reference/rvalue reference, то есть, писать два, три, четыре дубля функции.

Нет. Это требуется только в отдельных случаях.

C++11 стало нормой с ходу писать три конструктора классу (создания, копирования, перемещения)

Нет. В C++ давно уже нормой является не писать собственных конструкторов копирования и (начиная с C++11) перемещения. Компилятор сам делает это за вас.

Собственные конструкторы/операторы копирования/перемещения нужны только если ваш класс вручную реализует собственную политику владения каким-то ресурсом. Что, при правильном использовании готовых классов с RAII, случается очень редко.

В математике и во многих адекватных ЯП, которые не используют знак тождества для операции присвоения, константа — это непосредственное значение

Мы говорим не про математику (в которой, ЕМНИП, мутабельных переменных вообще нет) и не про другие ЯП. Мы говорим именно про C++, в котором, как вам кажется, есть три способа записи констант.

Так вот на счет заданных через define констант в C++ вы в корне заблуждаетесь.

константа — это цифра «2», а не идентификатор «a»

Если вы будете придерживаться этого взгляда на вещи в C++, то вас будут ждать неприятные открытия. Например, вот здесь у вас константы не будет, а будет временный неконстантный объект типа std::string:

#include <string>
#include <iostream>

using namespace std::string_literals;

#define MY_STR "hello"s

void f(std::string && s) {
    std::cout << "Temporary string: " << s << std::endl;
}

int main() {
    f(MY_STR);
}

Это я про чудеса соглашений по семантике разыменования указателя.

И тут мы снова вспоминаем про криворукого говнокодера, который пытается рассуждать о языке, которого не знает.

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

только ГЦЦ почему-то не даёт ворнингов.

Даёт, но только с флагом. (у MSVC тоже флаги нужны, но они по-моему включены в проекте создаваемой студией по умолчанию)

warning: use of uninitialized value '<unknown>' [CWE-457] [-Wanalyzer-use-of-uninitialized-value]

https://gcc.godbolt.org/z/8hzr98rvP

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

Первый турбопаскаль работал на 16 кб.

Спасибо, я практически и не сомневался.

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

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

Питон всё равно остаётся пластмассовой поделкой со своим интерпретатором (да, есть cython, но), со своей кривой горячей заменой, со своим кривым ООП, со своими кривыми тредами, со своей кривой сборкой мусора, со своими кривыми строками, со своими убогими лямбдами. Да и синтаксис у него для профессионального использования кривоватый. Дешёвка.

Вот почему биндинги тормозят в лиспе — это интересный вопрос, мне неочевиден ответ.

Скорее всего из-за преобразования строк. Питон использует сишные типы или напрямую, или с минимальными обёртками. Лисп из-за жирных строк должен каждую строку прочитать и по-честному преобразовать. Кроме того, в лиспе есть мода пользоваться всякими слоями переносимости типа CFFI, которые тоже добавляют накладных нагрузок. Но это только гипотеза и может зависеть от задачи. Хотя я и раньше сталкивался с подобным.

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

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

Добавляем сюда ваше ниасиляторство с ООП и понимаем, что с декомпозицией у вас очевидные проблемы. А способность декомпозировать – это одно из основных качеств разработчика. Которым вы, как можно увидеть, не обладаете.

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

Честно сказать, ты достал своими высерами. Я вообще не читаю то, что ты пишешь, но иногда само случайно на глаза попадается. Я и в отношении администрации недоумеваю, почему это терпят. Но в дополнение к тому, чтобы написать на тебя очередную (наверное, уже четвёртую) жалобу, я тебе советую открыть книжку «как пасти котов» и убедиться, что программисты бывают разных видов, у каждого свои сильные и слабые стороны. Их как минимум 5 или 7. Но не надо думать, что из них ты самый лучший. Касаемо функций на 350 строк - их полно в живой природе.

den73 ★★★★★
() автор топика
Последнее исправление: den73 (всего исправлений: 2)
Ответ на: комментарий от den73

Честно сказать, ты достал

Спокойнее нужно относиться к тому, что пишут в интернетиках.

своими высерами

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

Но в дополнение к тому, чтобы написать на тебя очередную (наверное, уже четвёртую) жалобу

Дайте угадаю: на то, что byko3y обзывает людей кретинами вы написали ровно ноль жалоб, правильно?

программисты бывают разных видов, у каждого свои сильные и слабые стороны. Их как минимум 5 или 7. Но не надо думать, что из них ты самый лучший.

Как из того, что я указал на слабую сторону byko3y следует, что якобы я думаю, что самый лучший?

По поводу оценок высказанных мной оценок качеств byko3y.

Представьте себе, что некий врач-офтальмолог начал активно критиковать методики операций на прямой кишке.

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

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

Какой коэффициент доверия будет к словам такого «врача»?

Вот и в отношении byko3y каждому не мешало бы вывести свой коэффициент доверия к его словам. Поскольку если персонаж начинает вести себя как тот, кто весь в белом, но при этом у него очевидные проблемы с качеством его же собственного кода, то данный коэффициент нуждается в понижении. Где-то до нуля.

Кстати говоря, в отношении меня это точно так же работает: мой код доступен, мои статьи доступны, мой блог все еще существует. Любой может оценить как мои собственные слова соотносятся с тем, что и как я делаю. И на основании этого решить, можно ли моему мнению доверять, в чем, когда и насколько.

Касаемо функций на 350 строк - их полно в живой природе.

Говнокода полно в природе, это да. Но,

  1. Это не есть хорошо и

  2. Мнение говнокодера, насколько бы убедительными словами оно не было оформлено, желательно отправлять напрямую в /dev/null.

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

Первый турбопаскаль работал на 16 кб.

Откуда дровишки?

Гугл говорит, что минимальные требования для TP 1.0 были:

  • Intel 8086 and Zilog Z-80 microprocessor based computers.

  • 64k bytes of memory.

  • 5 1/4" floppy disk for CP/M and PC DOS based systems.

  • 8" floppy disk for CP/M based systems.

Сам я программировал на TP 3.0 на Robotron 1715, там было 48k 64k RAM.

Про TP в 16k хотелось бы пруфов.

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

Какой ты новый алгоритм можешь вспомнить? Если говорить по поводу HTTP/2-3, то я не вижу новизны вообще

Ну читай «новый алгоритм» как «допиливание старого алгоритма», мне без разницы.

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

Да, все пять человек.

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

Про TP в 16k хотелось бы пруфов

Это должны быть особо толстые килобайты.

$ ls -sh TURBO.COM 
28K TURBO.COM
$ strings TURBO.COM | grep Z80
TURBO Pascal version 1.00 [CP/M-80, Z80] - Serial # $$$$$$$$$$$$
gremlin_the_red ★★★★★
()
Ответ на: комментарий от byko3y

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

я просто проходящий мимо фанат С++, а не какой-то эксперт, так что это норм.

В комментариях к видео Jason Turner, тоже часто люди удивляются каким-то возможностям С++

Например: https://youtu.be/rUESOjhvLw0

it’s actually shockingly simple. Like why THIS never gets into any c++ guidelines and books?

I’m surprised I’d never heard about it until just now.

Но у меня есть пример для тебя: https://github.com/microsoft/STL/issues/2720

Люди комитят в стандарт и даже для них неочевидно какое поведение должно быть:

https://github.com/cplusplus/draft/commits?author=CaseyCarter

https://github.com/cplusplus/draft/commits?author=cpplearner

https://github.com/cplusplus/draft/commits?author=frederick-vs-ja

Не знать чего-то не страшно :)

fsb4000 ★★★★★
()

Ладно, коллеги. Всем спасибо за беседу. Простите, если кого зря обидел. Я отпишусь от темы и звёздочку поставлю, т.к. мой интерес к теме исчерпан. Если кто-то хочет меня позвать, то кастуйте.

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

Ладно, коллеги. Всем спасибо за беседу. Простите, если кого зря обидел. Я отпишусь от темы и звёздочку поставлю, т.к. мой интерес к теме исчерпан. Если кто-то хочет меня позвать, то кастуйте.

Только не забудь скинуть ссылку на итог деятельности «Пишу телегу против плюсов». Спасибо!

Простите, если кого зря обидел.

Согласно моим наблюдениям, было с точностью наоборот... Обижался в теме в основном ты. Тот же byko3y куда более тонко реагирует на выпады в свой адрес. А матёрые «крестовики» — ребята вообще закалённые, их посылом на йух не смутишь. Их ведь компилятор по 100 раз на дню посылает 🙂

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

криворукого говнокодера, который пытается рассуждать о языке, которого не знает

Граждане, не надо так. Вас довольно интересно читать, не скатывайтесь.

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

Угу, скину (если не забуду и если вообще это дело дойдёт до конца).

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

8063 открытых бага https://github.com/rust-lang/rust/issues

Справедливости ради, не всё из этого баги.

Лоровские растовики знают раст на уровне дна, они понятия не имеют если что-то не работает это потому что не должно работать или это баг в компиляторе.

Хорошо, что на лоре кроме растовиков есть и такие эксперты как ты.

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

Вот в D пришла авторам блажь перенести битовые поля на уровень библиотеки. Кому-то стало от этого хорошо?

А кому плохо?

допустим, мне. а что? 😎

Ну так расскажи почему.

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

Ну как бы я уже несколько раз писал, что safe и unsafe — это два разных языка в составе одного.

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

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

Это тоже весьма субъективно. От «слегка сейф» толку не особо много. Это было бы «удобство», а не «безопасность». Уже сейчас нередко слышны заявления, что раст что-то там не гарантирует. По крайней мере, сейчас язык предоставляет однородные гарантии, а не «ну вот это сложно сделать, так что мы срежем угол, ведь очевидно, что тут надо быть внимательным».

Оставить только unsafe, только сделать его безопасным. Ы-ы-ы.

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

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

Про TP в 16k хотелось бы пруфов

Справедливости ради, я видел Паскаль, требующий примерно 16К и на котором оставалось место для отлаживаемой программы на машине с 32К памяти.

Это был «Ленинградский» Паскаль, написанный на Ленинградском же Форте (Баранов, Ноздрунов) и соответственно, существующий в памяти вместе с Форт системой. Не Турбо, конечно, но некоторое подобие IDE там было (в виде встроенного текстового экранного редактора). Если склероз не изменяет, можно было спокойно работать с Паскаль – программой на 6 экранов. Причём, в любой момент было возможно «выйти» в Форт. Н-да.

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

Но компилировался Паскаль в Форт и Фортом же и исполнялся. Быстро, но до скомпилированной Си – программы…

Было дело в Томском Университете, дисплейный класс ЕС1036 (? кажется). Каждый терминал в классе представлял собой автономно работающий, полноценный 8-и разрядный компьютер на ВМ80, подключенный к сети (можно было обмениваться с любым терминалом в классе и центральной машиной) и загружаемый по сети. Была такая кнопочка, позволяющая отправить ничего не подозревающему соседу свой (гм… «подготовленный», назовём это так :) экран. Наблюдать оторопь товарища — бесценно. 9 класс, физматшкола…

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

Тут вопрос вычисления коэффициента доверия к словам byko3y. Поскольку выглядит все стройно и красиво:

  • на C++ ничего работающего не написать;

  • Страуструп – менеджер-продажник;

  • стандарт пишут кретины;

  • константы в C++ задаются с помощью define;

  • первый Turbo Pascal работал в 16k.

Складно все. Только вот с реальностью не бьется :)

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

Еще можно добавить от него же:

  • я уже целых два месяца пишу на плюсах за деньги и хорошо знаю о чем говорю.

  • американцы не были на луне, современная физика говорит что это невозможно

  • Илон Макс это жулик, фалкон не может быть дешевле союза согласно законам физики.

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

Тенденция однако…

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

что ты там еще собрался защищать от разламывания

консистентность данных объекта

https://gcc.godbolt.org/z/8TnWaMsqb

struct A
{
    std::unique_ptr<char[]> data;
    int size;
    ...
    A& operator=(const A& other)
    {
        data.reset(new char[other.size]);
        std::copy(&other.data[0], &other.data[0] + other.size, &data[0]);
        return *this;
    }
};

Защитились? Защитились. Что могло пойти не так? Я подчеркиваю, что сейчас речь идет не про какую-то отдельную проблему конкретных операторов, а про фундаментальный изъян модификатора const при использовании его для переменных, который может точно так же проявиться в сотне других мест. не говоря уже о том, что в отдельных местах докатываются аж до const_cast.

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

Я сразу хочу подчеркнуть, что я не против идеи const_iterator и любых других mode_iterator — я лишь ставлю под сомнение пользу модификатора const. То, что в C++ нет адекватных механизмов трейтов/интерфейсов для удобства реализации различных режимов доступа? Ну извиняйте, не я проектировал язык.

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

Я согласен с такой позицией, а именно «зачем париться по поводу гарантий, если по итогу будем всё проверять вычитыванием кода и тестами?». Но при этом ты намекаешь, что const помогает в получении каких-то гарантий, несмотря на то, что рутинно стоишь в одном шаге от UB. И при этом ты лукавишь «честного слова программиста «не буду модифицировать» - мало». У ТЕБЯ ВЕСЬ КОД НА ЧЕСТНОМ СЛОВЕ ДЕРЖИТСЯ! Ну, и еще на тестах с санитайзерами.

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

Вы написали такой макрос. Он сам по себе говнокод, его в таком виде быть не должно было изначально. Тот факт, что вы сочли возможным его написать уже говорит многое о вас как о программисте
Большое количество мертвого кода в функции == говнокод.

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

Даже 133 строки – это в шесть раз больше приемлемого объема. Что == говнокод. Плюс демонстрирует вашу неспособность в композицию

Пилить код на произвольные куски по единственному критерию «должно быть меньше 25 строк» — это, я так понимаю, критерий качественного кода? Ну ок.

Далее ты не понял, что такой код вообще ни на какой стандартной либе не напишется, поскольку это lock-free код

Это не важно

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

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

Отэта поворот. То есть, это я не могу отличить суть от поверхностной формы.

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

Но стоит только кому-нибудь (вроде меня) высказать в ваш адрес тоже самое, что вы говорите в адрес Страуструпа или членом комитета по стандартизации C++, как высказавший это попадет по санкции

Да. Именно для этого это правило и придумано — слишком много желающих перейти на личности, а потом сделать то же самое с ответной стороны. По-хорошему в таком случае надо возражать по сути, но по сути возразить нечего, потому скатываемся в обзывания... как обычно. Лично я в данном случае все-таки предпочитаю акцентировать обсуждение не на том, кто посрал, а на том, кто поел — кто-то же всё это дело утвердил и ввел в эксплуатацию. Допустим, что внезапно мой проект вот прямо в таком неизменном виде будет подхвачен индустрией, на внутренние структуры возникнут зависимости, мешая производить какую-то доработку и рефакторинг, и код останется таким же ужасным спустя 10-20 лет. Можно было бы винить меня в том, что я сразу не написал идеальный код десятилетия назад, а можно вспомнить, что это был просто хобби проектик. Как это и было у Страуструпа. ну не умеет человек проектировать архитектуру сложных систем — ради бога, он ведь умеет писать код, посещать тусовочки, писать книжки, популяризировать разные технологии.

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

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

А так?

#include <iostream>
#include <string>
#include <string_view>

bool foo1()
{
    return true;
}

bool foo2()
{
    return true;
}

int main() {
    std::string s = "Helloooooooooo ";
    std::string_view sv = s;
    {
        std::string s2 = s + "World";
        if (foo1()) { sv = s2; }
    }
    if (foo2()) { std::cout << sv; }
}

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

Пример со string_view не очень хорош так как вот именно от такого misuse можно было легко защититься с zero cost in runtime просто запретив string_view(string&&), даже немножко удивлён что этого не было сделано. Можно привести гораздо более тонкие примеры которые даже очень опытные люди не сразу увидят

Да, временная переменная — не единственный способ получить висячий указатель. К сожалению, области жизни в C++ сломаны by-design, по-хорошему в таких случаях использование RAII недопустимо, все объекты должны вручную выделяться и высвобождаться — только так могут быть гарантии, что мелкая модификация кода не приведет к неожиданному смещения времени жизни объекта.

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

Оставляю каждому читателю право самому оценить истеричные вопли.

Именно в этом был и смысл: вытащить на свет куски вашего кода и дать послушать ваши оправдания. Далее пусть каждый судит сам.

Пилить код на произвольные куски по единственному критерию «должно быть меньше 25 строк» — это, я так понимаю, критерий качественного кода?

Нет, вы в очередной раз понимаете не правильно.

Это не важно

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

В огороде бузина, в Киеве дядька.

Впрочем, как обычно.

То есть, это я не могу отличить суть от поверхностной формы.

Вы в очередной раз понимаете не правильно.

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

По-хорошему в таком случае надо возражать по сути, но по сути возразить нечего

Возражать по сути вот этому:

  • Страуструп – это манагер-продажник;

  • Страуструп не умеет проектировать архитектуру сложных систем;

  • стандарты пишут кретины;

  • на C++ нельзя написать ничего работающего.

?

Да у вас с головой еще большие проблемы, чем можно было ожидать.

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

Что могло пойти не так?

Не так пошло изучение языка, в частности, тот факт, что operator= должен обрабатывать случаи x=x. Либо через сравнивание указателей, либо через использование идиомы tmp+swap.

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

А так?

gcc всё ещё предупреждает.

MSVC и clang нет, но в обоих из них есть санитайзеры, которые находят ошибку:

==33796==ERROR: AddressSanitizer: heap-use-after-free on address 0x11cce9fa0010 at pc 0x7fffef3a3292 bp 0x00034c0ff540 sp 0x00034c0ff558
READ of size 20 at 0x11cce9fa0010 thread T0
    <empty stack>

0x11cce9fa0010 is located 0 bytes inside of 32-byte region [0x11cce9fa0010,0x11cce9fa0030)
freed by thread T0 here:
==33796==WARNING: Failed to use and restart external symbolizer!
    #0 0x7ff7ba5b85dd in operator delete D:\a\_work\1\s\src\vctools\crt\asan\llvm\compiler-rt\lib\asan\asan_win_delete_scalar_size_thunk.cpp:42
    #1 0x7ff7ba5b19fe in std::_Deallocate<16,0> C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\xmemory:255
    #2 0x7ff7ba5b7868 in std::allocator<char>::deallocate C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\xmemory:830
    #3 0x7ff7ba5b6778 in std::basic_string<char,std::char_traits<char>,std::allocator<char> >::_Tidy_deallocate C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\xstring:4636
    #4 0x7ff7ba5b4c44 in std::basic_string<char,std::char_traits<char>,std::allocator<char> >::~basic_string<char,std::char_traits<char>,std::allocator<char> > C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\xstring:3000
    #5 0x7ff7ba5b12e6 in main C:\Users\fsb4000\source\repos\TestCpp\main.cpp:21
    #6 0x7ff7ba5b93a8 in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #7 0x7ff7ba5b92fd in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #8 0x7ff7ba5b91bd in __scrt_common_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330
    #9 0x7ff7ba5b941d in mainCRTStartup D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:16
    #10 0x7ff8947e7033 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180017033)
    #11 0x7ff895502650 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180052650)

previously allocated by thread T0 here:
    #0 0x7ff7ba5b84ea in operator new D:\a\_work\1\s\src\vctools\crt\asan\llvm\compiler-rt\lib\asan\asan_win_new_scalar_thunk.cpp:41
    #1 0x7ff7ba5b5832 in std::_Default_allocate_traits::_Allocate C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\xmemory:79
    #2 0x7ff7ba5b159d in std::_Allocate<16,std::_Default_allocate_traits,0> C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\xmemory:235
    #3 0x7ff7ba5b6edf in std::allocator<char>::allocate C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\xmemory:834
    #4 0x7ff7ba5b390d in std::basic_string<char,std::char_traits<char>,std::allocator<char> >::basic_string<char,std::char_traits<char>,std::allocator<char> > C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\xstring:2660
    #5 0x7ff7ba5b153c in std::operator+<char,std::char_traits<char>,std::allocator<char> > C:\Program Files\Microsoft Visual Studio\2022\Professional\VC\Tools\MSVC\14.32.31326\include\xstring:4744
    #6 0x7ff7ba5b1237 in main C:\Users\fsb4000\source\repos\TestCpp\main.cpp:19
    #7 0x7ff7ba5b93a8 in invoke_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:78
    #8 0x7ff7ba5b92fd in __scrt_common_main_seh D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:288
    #9 0x7ff7ba5b91bd in __scrt_common_main D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_common.inl:330
    #10 0x7ff7ba5b941d in mainCRTStartup D:\a\_work\1\s\src\vctools\crt\vcstartup\src\startup\exe_main.cpp:16
    #11 0x7ff8947e7033 in BaseThreadInitThunk+0x13 (C:\WINDOWS\System32\KERNEL32.DLL+0x180017033)
    #12 0x7ff895502650 in RtlUserThreadStart+0x20 (C:\WINDOWS\SYSTEM32\ntdll.dll+0x180052650)

SUMMARY: AddressSanitizer: heap-use-after-free

https://gcc.godbolt.org/z/W4W8fe9d6

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

Да хоть C++98. Привлечение исходников cfront 1.0 к разговору о константности в C++ не имеет смысла, т.к. эта самая константность, о которой идет речь, появилась сильно позже cfront 1.0

Ее суть, «неизменяемая переменная», осталась такой же, как в cfront 1.0, поменялась лишь косметика-сахарок.

Во-вторых, у вас проблема не с list, у вас проблема с char * и const char *. И ее можно проиллюстрировать гораздо более простым примером
void f(char * str) { (void)str; }

Как раз в таком варианте проблема решается банальной заменой декларации на void f(const char * str). А вот в случае list<char *> этого сделать уже нельзя, потому что list<char *> нельзя просто привести к list<const char *>. И получаем несовместимость типов на ровном месте.

Причем, каких-то более менее универсальных и удобоваримых способов решения проблемы (вроде copy-on-write) в C++ реализовать невозможно, поскольку в нем by-design поломатое время жизни переменных, как указано выше:
юнионы в C++ (комментарий)
То есть, любая манипуляция ссылками значит, что ты остаешься без каких-либо гарантий со стороны компилятора. А для обеспечения гарантий работоспособности без ссылок придется копировать значения на каждый чих, что похоронит производительность.

Ваша функция, которая ждет list<T> может получать не list и даже не какой-то другой тип контейнера. А пару итераторов (или объект-рендж)

Шаблонная функция, которая ждет list<T>, может получить любой T так-то, даже итераторов-ренжей не нужно. Проблема не в функции, а в данных. Если нам нужно все-таки этот список сохранить в какой-то области памяти и/или передать виртуальным функциям, то автогенерация функций через шаблоны со специализациями const char * и char * уже не прокатывает.

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

Но для такого решения нужно уметь декомпозировать

Уже надекомпозировались так, что hello world на ренжах пару секунд компилируется.

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

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

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

Это требуется только в отдельных случаях

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

В C++ давно уже нормой является не писать собственных конструкторов копирования и (начиная с C++11) перемещения. Компилятор сам делает это за вас

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

Собственные конструкторы/операторы копирования/перемещения нужны только если ваш класс вручную реализует собственную политику владения каким-то ресурсом. Что, при правильном использовании готовых классов с RAII, случается очень редко

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

Мы говорим именно про C++, в котором, как вам кажется, есть три способа записи констант

Ололо, где я такое писал?

Если вы будете придерживаться этого взгляда на вещи в C++, то вас будут ждать неприятные открытия. Например, вот здесь у вас константы не будет, а будет временный неконстантный объект типа std::string

Умоляю, я в гробу видал эти чудеса неявного поведения C++, который без спроса приводит всё ко всему так, как ему вздумается. Удачи искать баги и читать ошибки компиляции в таком коде. Потому я на своих классах делаю explicit конструкторы.

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

Про TP в 16k хотелось бы пруфов

Скачал 1.0 и запустил в DosBox. Таки да, на 16 кб не работает, работать начинает с 35 кб. То есть, ему нужно себя всего загрузить в оперативу.

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

Ололо, где я такое писал?

Здесь: юнионы в C++ (комментарий)

И очень долго время под соусом const существовало три независимых вещи:

— compile-time константы, каковые были во всех остальных языках, например #define x 42;

Так вот через define в C++ константы не задавались.

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

Не знать чего-то не страшно

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

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

От того, что «уже все рассказали» проблема каким-то образом становится менее серьезной?

Стало понятно, что проблема в вашем ниасиляторстве и неспособности воспринимать реальность такой, какая она есть.

И это не серьезная проблема, потому что это ваша проблема. Вряд ли она кого-то волнует.

Я смотрю на функции стандартной либы

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

Стандартная либа (да и вообще универсальные повторно используемые либы, предназначены для применения в самых разнообразных сценариях и условиях) – это отдельная история.

Я все-таки писал про случаи, когда конструктор нужен, и тогда нужно писать все три, а также два оператора присвоения.

Этих случаев на практике должно быть минимальное количество.

Умоляю, я в гробу видал эти чудеса неявного поведения C++

  1. Подучите матчасть.

  2. Глаза разуйте.

В примере явным образом создается объект типа std::string, никаких неявных приведений там нет.

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

eao197: вы будете плодить код, от которого пришедшие на ваше место будут плеваться. И, вероятно всего, вполне оправдано

byko3y: Меньше всего меня колышет судьба человека, которого возьмут кодить вместо меня

<A FEW MOMENTS LATER>

fsb4000: Не знать чего-то не страшно

byko3y: Страшно, если тебе нужно сдать проект к сроку, а у тебя непонятно что в нём происходит, потому что один чел из команды решил показать, какой он эксперт по C++, а потом ушел в другую фирму, показывать там, какой он эксперт.

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

потому что один чел из команды решил показать, какой он эксперт по C++

А как же код-ревью? Почему в проекте оказался код, который другие люди не понимают? Или это какая то шарага, где писал сначала один программист, потом наняли другого взамен первого. То есть работал лишь один человек, поэтому никаких код ревью не было?

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

А вот в случае list<char *> этого сделать уже нельзя, потому что list<char *> нельзя просто привести к list<const char *>. И получаем несовместимость типов на ровном месте.

Так это же логично, что если у нас есть контейнер указателей на мутабельные объекты, то это, мягко говоря, несколько отличается от контейнера указателей на немутабельные объекты.

Ну вот так в C++ устроено. А еще в С++ нет GC. А еще в C++ можно запросто получить протухший указатель.

Кричать о том, что все это криво, неудобно и опасно нет смысла.

Во-первых, есть альтернативы. Не нравится C++ – берете то, что нравится.

Во-вторых, если вам таки приходится писать на C++, то играть нужно по имеющимся правилам. С учетом того, что в C++ A<T*> и A<const T*> – это разные типы, нет GC и запросто получить повисший указатель. Если вам это не нравится, то см.пункт первый.

Конкретный пример этой проблемы — список списков.

Так приведите уже конкретный пример. Хватит уже щеки надувать и трепать языком о каких-то абстрактных сложных системах.

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

А как же код-ревью?

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

Се ля ви.

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

Когда bus-фактор 1 какой тут код ревью… У нас код ревью только для студентов практикуется.

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

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

Это тоже весьма субъективно. От «слегка сейф» толку не особо много. Это было бы «удобство», а не «безопасность»

Ты всегда получишь «слегка сейф» на чем угодно — в этом и заключается фундамент моей претензии. Асинхронное выполнение, ввод-вывод — ансейф. Подключил сишные биндинги (а куда ты от них денешься) — ансейф. Lock-free алгоритмы — снова ансейф. Решил пооптимизировать — опять ансейф. Кстати, Ариан упал именно из-за оптимизаторов. Раст в какой-то степени позволяет бороться с теми, кто заметает проблемы под ковер, но в плане логики грамотного кодописания ничего не заменит и не даст гарантии работоспособности.

ЯП — это всегда баланс, но когда за дело берутся инклюзивно-толерантные, то получается вот это.

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

Без оптимизаторов на том железе ариан бы просто не взлетел, бггг. Вы бы лучше молчали про космос, это не Ваша тема.

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

американцы не были на луне, современная физика говорит что это невозможно

Вот это уже заявочка... Я в этом же треде опроверг это утверждение, но ты мне снова пытаешься его приписать.

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

Опять, я никогда такого не писал.

byko3y ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.