Здравствуйте, SkyDance, Вы писали:
E>>Будущее мобильной разработки, Tizen 2.0. По моему, шикарно... 6 new, 3 каста, 1 delete и даже E_SUCCESS
SD>Помнится, я в одном из форумов объяснял epic fail Symbian'а и тотальный уход в пользу iOS/Android именно подобным кодом и подходом к программированию вообще. Некоторые были не согласны, и превозносили Symbian как прекрасную ОС, якобы предательски убитую г-ном Элопом (и уже под это дело вагон теорий заговора).
Мне кажется, тут ты не прав. Разработчик подтянется к любой ОСи, дружественной к нему или нет. Главное, чтобы ось была популярной у пользователей. Тот же win32 не слишком-то дружественен к разработчику, но тем не менее
Re[48]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
Здравствуйте, jazzer, Вы писали:
J>Мой формальный ответ такой: код на исключениях элементарно переписывается один-в-один на код с кодами возврата и return'ами, для которого все давно доказано (то, что множественные return'ы переписываются в гроздь if'ов, надеюсь, специально доказывать не надо?)
"Код на исключениях элементарно переписывается один-в-один на код с кодами возврата и return'ами" — Вот конкретно это утверждение неплохо бы доказать, раз уж ответ "формальный". Ну и слово "элементарно" здесь точно лишнее, причем по двум причинам: 1) "формально" оно никакой смысловой нагрузки не несет; 2) неформально оно неверно, если код и переписывается, то отнюдь не элементарно.
Re[49]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
Здравствуйте, igna, Вы писали:
I>Здравствуйте, jazzer, Вы писали:
J>>Мой формальный ответ такой: код на исключениях элементарно переписывается один-в-один на код с кодами возврата и return'ами, для которого все давно доказано (то, что множественные return'ы переписываются в гроздь if'ов, надеюсь, специально доказывать не надо?)
I>"Код на исключениях элементарно переписывается один-в-один на код с кодами возврата и return'ами" — Вот конкретно это утверждение неплохо бы доказать, раз уж ответ "формальный". Ну и слово "элементарно" здесь точно лишнее, причем по двум причинам: 1) "формально" оно никакой смысловой нагрузки не несет; 2) неформально оно неверно, если код и переписывается, то отнюдь не элементарно.
Таки элементарно: бросание исключения переписывается в виде установки глобального объекта исключения + return, пробрасывание исключения — проверка установленного исключения и return, если оно установлено и нету catch, а если catch есть — goto не него (вставляется после каждой операции, которая может бросить — для пущей формальности можно вставить вообще после каждой операции).
И этот код даже неверен, поскольку g может быть вызвана в твоем же обработчике исключения, поэтому перед присваиванием переменной current_exception нужно проверить ее значение.
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, Evgeny.Panasyuk, Вы писали:
EP>>Редкий? EP>>Выделение памяти в приложении, внутри структур данных — это редкость?
_>Редким является не выделения памяти, а ситуация когда оно даёт сбой. И из факта особенности этой ситуации следуют соответствующие выводы насчёт её обработки...
Это как раз последствие нашей "разбалованности" парадигмой Win32 про виртуальное адресное пространство, массированое строительство азиатских заводов микроэлектроники и "memory is not a resource".
Тут в комментариях выше уже справедливо указывали микроконтроллеры с набортной нерасширяемой памятью, щедрых 4 килобайта... И это реальность сегодняшнего дня, а не бородатые "во времена моей молодости 40 баксов за мегабайт". Да и на младшие Raspberry Pi народ ворчит, что младшие модели всё ж обделены памятью — чуть куда рыпнулся сверх плана, всё, счастье кончилось.
Здравствуйте, alex_public, Вы писали:
_>Здравствуйте, MTD, Вы писали:
MTD>>Вот из Adobe Illustrator SDK, обрати внимание, как в середине чуваки сами запарились проверять код возврата и тупо забили на обработку ошибок:
_>Посмотрел повнимательнее на ваш код... Ха, так это же как раз отличный пример того, о чём я говорил. Именно реализация такой логики (зря вы подумали что они забили в середине — это же очевидно логика такая) как раз и очень неудобна с помощью исключений.
У нормальных людей такой SDK не должен был вообще скомпилиться (-Wall -Werror), поэтому никогда бы не вышел в свет...
Re[48]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
Здравствуйте, jazzer, Вы писали:
J>Концептуально исключения — это просто сахар для кодов возврата (а errno будет еще более близкой аналогией).
Кстати, про "просто сахар". Я как-то виедел один фреймворк, писанный какое-то время назад людьми, которым исключения были недоступны по техническим причинам.
так там у них был такой классец, OpResult, у которого был operator bool и был перегруженный c собой в качестве аргумента,и ещё несколько перегрузокнесколькими типами + всякие доп. аргументы operator()
В целом странненько, но к этим палочкам-скобочкам очень быстро привыкаешь. Обработку прозевать трудно...
Сейчас, кстати, можно вообще какой-нибудь $ выбрать, например...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Erop, Вы писали:
E>Здравствуйте, jazzer, Вы писали:
J>>Начнем с того, что у класса, который не обеспечивает базовой гарантии, даже деструктор нельзя звать — инварианты-то нарушены, а значит, деструктор может сделать все, что угодно, расстрелять любую память, позвать деструкторы дважды и т.п. В отсутствии базовой безопасности поведение программы при вылете исключения в общем случае неопределено, ее даже грохнуть корректно нельзя.
E>В смысле? конструктор обеспечивает базовую гарантию, деструктор обеспечивает некидание исключений. Что тут не так?
Т.е. если он обломался, то объект, с которого мы мували, можно корректно удалить, позвав деструктор, так?
Тогда можно, но это уже инвариант "указатель всегда указывает на память, которую можно безопасно delete"
E>А сравнить я предлагаю с кодом, который сам по себе гарантий не обеспечивает...
Т.е. у которого даже деструктор позвать нельзя? Инварианты же нарушены, например, указатель может указывать хз куда, а ты ему delete. Это какой-то патологический случай.
J>>
void reserve(size_t new_capacity)
{
char* old_buf = buf_;
buf_ = new char[new_capacity*sizeof(T)]; // если new бросает - в объекте ничего не меняется
capacity_ = new_capacity;
const size_t orig_size = size_;
size_=0;
// итак, сейчас у нас buf_ указывает на нововыделенный пустой буфер
// capacity соответствует его размеру и size_ нулевой (так как ничего в буфере нету)
// Т.е. вектор уже в рабочем состоянии (пустой), базовая гарантия в плане инвариантов
// УЖЕ выполнена (я ведь обещал, что это элементарно?)
// Осталось разобраться с утечками.
// Для этого в конце, независимо ни от чего, прибиваем old_buf со всем содержимым
// (этот прибиватор вполне себе общего назначения и его можно объявить и снаружи):struct OnScopeExit {
char* old_buf;
size_t orig_size;
~OnScopeExit() {
for (size_t i=0; i<orig_size; ++i) ((T&)( old_buf[i*sizeof(T)] )).~T();
delete[] old_buf;
}
} on_scope_exit = { old_buf, orig_size };
// все, базовая гарантия достигнута полностью, можно начинать изгаляться над буфером
// попробуем покопировать, нехай исключения летятfor (; size_<orig_size; ++size_)
new (&buf_[size_*sizeof(T)]) T(std::move( (T&)old_buf[size_*sizeof(T)] ));
// по окончании работы функции size_ показывает количество успешно скопированных объектов
}
Как я и обещал, все элементарно.
E>Это сейчас ещё даже во многих популярных боевых компиляторах не заведётся... E>Может быть когда-нибудь, лет через пять-десять...
Э, с чего бы это вдруг? BOOST_SCOPE_EXIT написан лет 5 как и тестировался на gcc3, который хз сколько лет везде крутится.
Ну и лямбду я заюзал исключительно для краткости. То же самое элементарно достигается локальной структурой, просто писанины _чуть_ больше будет.
E>Но даже то, что написано тут мне не нравится категоррически, очень мутно и сложно.
Ну если это для тебя мутно и сложно, то я не знаю прям...
ОК, я добавил там комментариев и по просьбам трудящихся избивался от лямбды и scope_exit.
ассерты и проверки, которые у тебя там ниже, извини, вставлять не буду — лень.
Все еще мутно и сложно?
E>Ну давай всё равно почитаем... E>Ты, кажется, хотел разрушать в случае неудачи все данные, или все скопированные данные, я же не перепутал? E>Тут, вроде как, делают что-то другое...
Я оставляю в вектор все данные, которые удалось скопировать, все остальное прибиваю.
Можно было бы вообще все прибить, но оставить то, что можно оставить, мне кажется полезнее.
E>Скажем, если этот массив, окажется полем структуры из двух параллельных массивов, то уже будет немного неприятно. Прийдётся по любому исключению грохать содержимое обоих...
Что такое параллельные массивы? Ты уже второй раз их упоминаешь.
J>>Давай теперь то же на кодах возврата. Особенно сексуально будут выглядеть коды возврата из конструктора неизвестного типа и их смешение с ошибкой выделения памяти для буфера. E>Там не будет std::vector'а, там надо как-то иначе. E>Например, у типа будет не конструктор перемещения, а перегруженная функция ERR_CODE move_array_item( T& dst, T& src ), которая вернёт, смогла или нет,.. E>точный аналог втоего кода тогда будет выглядеть как-то так:
ERR_CODE reserve( size_t new_capacity )
E>{
E> ERR_CODE res = EC_Ok; // это мантра ;)
E> if( new_capacity <= capacity_ ) { // Этого у тебя не было, но положим,
// что ты про это забыл потому что код очень простой и понятный ;)
E> return res;
E> }
E> assert( new_capacity > 0 );
E> // Создаём копию буфера, и передвигаем в неё данные
E> char* extra_buf = new char[new_capacity*sizeof(T)] );
E> if( extra_buf == 0 ) {
E> return EC_MemoryError;
E> }
E> size_t cp_size = 0;
E> while( cp_size < size() && IsOk( res ) ) {
E> res = move_array_item( ((T*)extra_buf)[cp_size], ((T*)buf_)[cp_size] );
E> }
E> // тут мы ещё можем решить, что разрушать. Например, можно разрушать
// старый буффер только если полностью получилось скопировать новый
E> if( IsOk( res ) ) {
E> std::swap( extra_buf, buf_ );
E> std::swap( size_, cp_size );
E> capacity_ = new_capaciry;
E> }
E> while( cp_size > 0 ) {
E> ( --cp_size + (T*)extra_buf )->~T(); // Разрушаю всё-таки с конца...
E> }
E> delete[] extra_buf;
E> return res;
E>}
E>длиннее, но проще. + учтено чуть больше всяких мелочей и содно выбрать что в случае аварии делаем.
Где ж проще? Я проверить new_capacity <= capacity_ забыл, да, но ты ж не будешь называть это ключевым отличием, я надеюсь
А то я скажу, что у тебя cp_size в цикле не инкрементится
Удалять с конца абсолютно бессмысленно, ибо нигде не сказано, что объекты вставлялись в вектор по порядку или что потом на них не было напущен sort.
Так что "больше всяких мелочей" никакой рояли не играют в данном случае.
E>Но это всё равно класс спректированный под исключения. Например, если мы вспомним, что ещё бывают всякие там insert и erase, которым надо сдвигать куски буфера, то у нас начнутся проблемы.
Не начнутся. E>Либо нам надо будет написать походие циулы несколько раз. А всё потому, что мы не можем позволить себе иметь кусок памяти, где просто память и объекты перемешаны как попало...
А функции на паре указателей для "похожих циклов" написать религия запрещает?
E>Зато, если без исключений пишем, или пости без исключений, например, то можно функцию move_array_item сделать чуть прикольнее. E>}[/c] ну и для простоты ещё и такой:
Ну то есть мой OnScopeExit выше. Да, если писать реальный класс вектора, то многое уйдет во вспомогательные функции и все будет еще лаконичнее и у тебя, и у меня.
E>Ну и с этой инфраструктурой мы легко можем теперь писать разные штуки вроде insert... E>Кстати, я так думал, что ты заведёшь внутри reserve ещё одну копию вектора, в котором зарезервируешь нужный буффер, потом перенесёшь элементы и обменяешь это всё.
Зачем, если можно проще? Правда, для тебя это внезапно оказалось "мутно и сложно"
E>>>Ну тогда покажи то же но про два параллельных массива, например... J>>это еще что? У тебя развлечение такое — мне задания на кодинг выдумывать? E>Я пытаюсь тебе показать, что сохранять инварианты в случае исключения весьма небесплатно. И даже гарантировать отсутствие утечек не всегда просто.
Ничего не бывает бесплатно, если ты именно это хотел доказать, то ты не того адресата выбрал.
J>>Ты не подменяй тему обсуждения, а... Речь шла о том, что код становится запутанным — я показал, что не становится. J>>Если хочешь обсудить оптимизацию и как она влияет на понятность кода — я готов. Заодно расскажешь, как замечательно делается аналогичная оптимизация на кодах возврата. E>Во-первых, я не сторонник кодов возврата, я всего лишь понимаю люедй, которые не хотят связываться с исключениями, так что я могу исказить позицию тру сторонников. E>Во-вторых, тему я не подменяю. Имелось же в виду "программы аналогичные по функционалу и эффективности", иначе смысла нет обсуждать. Ясен пень что и так и сяк можно написать просто, а можно сложно, можно эффективно, а можно неэффективно. Надо сравнивать эффективно и хорошо там и эффективно и хорошо там...
Ну и где же твое "и там и там", если ты все время хочешь сравнить код с гарантиями с кодом без гарантий?
E>>>2) Ничего клнцептуально сложного в нём, тем не менее нет, гарантии безопасности -- зна-а-а-ачительно сложнее концептуально J>>Да что ты говоришь. Убрать за собой в случае вылета исключения — это же так сложно. E>Конечно сложно, так как E>1) Вылет может произойти где угодно
Да E>2) "Где угодно" вернуться к инвариантам всех данных во всей программе может быть трудно, если вообще возможно.
Достаточно возвращаться в инвариантам локально и документировать, где у тебя какой уровень безопасности. E>А в это время может случиться какая-нибудь клизьма. Ну там деструктор какой-нибудь нежданно куда-то слазит, или ещё чего...
э?
J>>Самая простая концепция — вообще забить на любую обработку ошибок. Текст программы становится ну просто загляденье. И никаких гарантий — в точности то, что ты хочешь E>Почему? Писать везде if( IsOk( res ) ) res = следующая_часть_обработки( параметры ); так уж сложно?
Нет, не сложно. Объясни вот только теперь, почему в приведенном адобовском коде этого не написали?
И почти везде в реальности забивают на повсеместную проверку кодов возврата, если только не применяются драконовские административные меры?
ЗЫ Статический анализатор не поможет против того адобовского кода
Здравствуйте, Vzhyk, Вы писали:
V>То есть предлагают на них организовывать логику программы? — это бред.
Ну вроде как открытым текстом люди пишут...
Вот читаем мы какой-то текстовый файл конфига. В одной строчке не ту циферку встретили -- кидаем исключение. Интересно, кстати, какое?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, enji, Вы писали:
E>Мне кажется, тут ты не прав. Разработчик подтянется к любой ОСи, дружественной к нему или нет. Главное, чтобы ось была популярной у пользователей. Тот же win32 не слишком-то дружественен к разработчику, но тем не менее
Фиг бы с ним, с win тридцать вторым! Уж на что УГ было АПИ у старой макоси, а писали жеж.
Вообще разработчиков обычно, если это не бесплатный опенсорс, спрашивают не "нравится тебе ОС" или нет, а 2ты арплату получать хочешь?"
просто если ОС особенно *своеобразная*, то зарплата должна быть чуть больше...
и да, на мой взглаяд симбиан для телефона намногоболее удачная платформа, чем андроид.
может на андроид легче перенести какое-нибудь большое приложение, но, зато, на симбиане телефоны хорошие получались, а не глюкавое УГ с рывками в интерфейсе и батарейкой на полдня...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[50]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
Так мы не получим процедурного кода, тем не менее...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
On 28.02.2013 15:09, Erop wrote:
> Вот читаем мы какой-то текстовый файл конфига. В одной строчке не ту > циферку встретили -- кидаем исключение. Интересно, кстати, какое?..
Абсолютно логично и правильно делают. Программа должна делать только то,
что написано в требованиях и ни в коем случае не делать что-то другое.
Но, есть момент, что если в требованиях написано, что если в
конфигурации есть ошибки, то нужно сделать то-то и тот-то и продолжить
работу, то и в этом случае я бы использовал исключение, ибо ситуация
редкая и не входит в логику программы. Единственный момент, когда
исключения не нужны: если у нас в программе зашита некая дефолтная
конфигурация и мы должны ее использовать, если пользователь не установил
значения некоторых параметров другими. Все.
Posted via RSDN NNTP Server 2.1 beta
Re[51]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
I>Это никакое не формальное доказательство.
Извини, теоремы-леммы, чтоб тебя потешить, я писать не буду. Но если очень хочешь — пиши в личку, о цене договоримся.
I>И этот код даже неверен, поскольку g может быть вызвана в твоем же обработчике исключения, поэтому перед присваиванием переменной current_exception нужно проверить ее значение.
Теперь твоя душенька довольна?
Здравствуйте, jazzer, Вы писали:
E>>Так мы не получим процедурного кода, тем не менее... J>Да фроде чифтый фортран
Это никак не гарантирует процедурности...
J>А что "тем не менее"?
ну ты пока что якобы показал, что программа с обработкой ошибок на исключениях эквивалентна некому весьма УГ коду, где куча инфы передаётся через статические переменные, а весь код утыкан конструкциями вида "если в какой-то статической переменной такое-то значение, то goto куда-то"...
ты правда считаешь, что хотя бы типичная работоспособная программа на С с кодами возврата там и прочими ужосами написана так плохо?..
IMHO, ты только продемонстрировал мой тезис, что код на исключениях эквивалентиен совершеннийшеё лапше из goto по статичесием ппеременным, что само по себе ужасно, и с чем именно и боролся Дейкстра, когда предлагал процедурное программирование...
Теперь поясни мне, пожалуйста. Я чего-то не понял в твоей аргументации? Или оно на самом деле не эквивалентно? Или таки ты сам же и доказал, что программы с массовыми исключениями полный аналог сорвершенного говно-goto-нереинтерабельного кода?..
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Vzhyk, Вы писали:
V>Абсолютно логично и правильно делают. Программа должна делать только то, V>что написано в требованиях и ни в коем случае не делать что-то другое.
Это логично только в том случае, если мы этот парсер для этой программы написали и забыли.
Индустрия программирования же стремиться разрабатывать переиспользуемый код. поэтому неплохо бы, что бы код функции ReadInteger можно было бы использовать и в той программе, где по буковкам в таком поле надо дохнуть и втой, где надо сказать, "вы знаете, у вас там в профиле всё хорошо, но вместо уровня доходов написано "не скажу", бум работать с таким профилем?"...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
On 28.02.2013 16:07, Erop wrote:
> Индустрия программирования же стремиться разрабатывать переиспользуемый > код. поэтому неплохо бы, что бы код функции ReadInteger можно было бы > использовать и в той программе, где по буковкам в таком поле надо > дохнуть и втой, где надо сказать, "вы знаете, у вас там в профиле всё > хорошо, но вместо уровня доходов написано "не скажу", бум работать с > таким профилем?"...
Опять перешли к сферическим коням. Не надоело еще?
Индустрия программирования все, что делает — это выполняет различные
заказы по программированию и совсем не заниматся стремлениями.
Если заказчик оплатил различные извращения, то мы их будем делать, если
не оплатил, но не будем, ибо Хроноса в родственниках ни у кого из нас
нет и предсказать, что будет нужно не можем.
Здравствуйте, Vzhyk, Вы писали:
V>Индустрия программирования все, что делает — это выполняет различные V>заказы по программированию и совсем не заниматся стремлениями.
Ещё есть и ретейл, вообще-то. Есть аппаратно-програмные комплексы и т. д...
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[52]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен
Здравствуйте, jazzer, Вы писали:
J>Теперь твоя душенька довольна?
Ну по крайней мере теперь ты видишь, что "переписать код на исключениях на код с кодами возврата" вовсе не элементарно. "Элементарно" тут скорее сделать ошибку при этом переписывании.
Re[51]: Слушайте, люди добрые, а правда, есть мат аппарат анализа кода с иключен