Re[2]: Тестовое задание C++ win
От: Кодт Россия  
Дата: 01.12.09 10:35
Оценка:
Здравствуйте, Alexey_VL, Вы писали:

A_V>Теоретически, в g() могли переставить указатели на что-нибудь другое, и не удалить то, на что они указывали. Лечится с помощью void g( char * const, char * const, size_t ); Хотя в реальных проектах пока ни разу не встречал такой защиты.


Наложение константности на данные, передаваемые по значению (собственно указатели) — большого смысла не несёт.
Всё равно наружу любые изменения не просочатся.
А внутри — элементарно снимается
void g(char* const a)
{
    char* aa = a;
    .......
    aa = bbbb;
    .......
}

Но что в этом ужасного — непонятно.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[6]: Тестовое задание C++ win
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 01.12.09 11:07
Оценка:
Здравствуйте, andrey.desman, Вы писали:

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


S>>>И if-ы лишние. delete отлично удаляет нулевой указатель.

K>>не все компиляторы одинаково полезны.

AD>Компилятор здесь ни при чем. delete, равно как и free нулевого указателя — это законная операция, так что смысла в проверках нет, если только тебе не платят за килограммы кода

Ты не можешь гарантировать то, что delete не переопределён и работает корректно.
Sic luceat lux!
Re[4]: Тестовое задание C++ win
От: igna Россия  
Дата: 01.12.09 11:14
Оценка: +3
Здравствуйте, Kernan, Вы писали:

K>Соглашусь. В catch delete лучше убрать.


catch, который ловит что попало и это "что попало" затем не перебрасывает, тоже лучше убрать.
Re[3]: Тестовое задание C++ win
От: Alexey_VL  
Дата: 01.12.09 11:15
Оценка:
Здравствуйте, Кодт, Вы писали:

К>Наложение константности на данные, передаваемые по значению (собственно указатели) — большого смысла не несёт.


Это я ступил. Просто была давно подуманная мысль про char * const , что она так работает. Поскольку в реальности эта мысль не применялась и как следствие не продумывалась заново, она до сегодняшняего дня лежала в моске как истинная
Мафиозная диктатура это нестабильность. Если не мафиозная диктатура, то Конституция и демократия.
Re[4]: Тестовое задание C++ win
От: Alexey_VL  
Дата: 01.12.09 11:17
Оценка:
Имеется ввиду — char * const для передачи данных в функции.
Мафиозная диктатура это нестабильность. Если не мафиозная диктатура, то Конституция и демократия.
Re[7]: Тестовое задание C++ win
От: Bell Россия  
Дата: 01.12.09 11:17
Оценка: +1
Здравствуйте, Kernan, Вы писали:

K>Ты не можешь гарантировать то, что delete не переопределён и работает корректно.


Ну почему же
Перегрузить можно operator delete, а поведение delete expression (о котором и идет речь) для нулевого указателея четко специфицировано стандартом, и

has no effect (5.3.5/2)

Любите книгу — источник знаний (с) М.Горький
Re[5]: Тестовое задание C++ win
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 01.12.09 11:43
Оценка: -5 :)
Здравствуйте, Кодт, Вы писали:

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


К>>>auto_ptr и boost — это как раз и есть воплощение KISS, в отличие от мосвелосипедстроймонтажа.

K>>Каки бусты/stl в 3-х строчках кода, а? Надеюсь, ты не из тех кто начинает использовать стратегии, где достаточно православного switch?

К>Привет участникам синтаксического оверхеда(tm)!

К>
К>                                    #include <vector>

К>void f( size_t n )
К>{
К> сhar *a = NULL;                    std::vector<char> a(max(n,1));
К> char *b = NULL;                    std::vector<char> b(max(n,1));
  
К> if (n <= 0)                        //
К>     return;                        //
К> try                                //
К> {                                  //
К>    a = new char[n];                //
К>    b = new char[n];                //
К>    g( a, b, n );                   g(&a[0], &b[0], n);
К> }                                  //
К> catch (...)                        //
К> {                                  //
К>    if (a) delete [] a;             //
К>    if (b) delete [] b;             //
К> }                                  //
К> if (a) delete [] a;                //
К> if (b) delete [] b;                //
К>}
К>

К>Ну и у кого из нас три строчки?
вот только вопрос есть, тебе на вход приходит 0, а на вход функции g ты передёшь 1. Подмена понятий, однако. Хотя код неплох, есть чему поучится
Sic luceat lux!
Re[7]: Тестовое задание C++ win
От: andrey.desman  
Дата: 01.12.09 12:53
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Ты не можешь гарантировать то, что delete не переопределён и работает корректно.

А еще я не могу гарантировать, что завтра мне кирпич на голову не упадет
Re[6]: Тестовое задание C++ win
От: Кодт Россия  
Дата: 01.12.09 13:47
Оценка:
Здравствуйте, Kernan, Вы писали:

K>вот только вопрос есть, тебе на вход приходит 0, а на вход функции g ты передёшь 1. Подмена понятий, однако. Хотя код неплох, есть чему поучится


Если ты присмотришься внимательно, то заметишь: на вход g приходит 0.

Но в конструкторы векторов действительно приходит 1. Это нужно затем, чтобы эмулировать поведение new char[0].
Дело в том, что char* p = new char[0] — это валидный ненулевой неразыменовываемый (обрати внимание на эти три слова!) указатель за конец массива.

Вектор же не оперирует указателями. Он отдаёт итераторы, разыменовывая которые, получаем ссылки (*v.begin()); или же сразу ссылки (v[0], v.front()).
Потом ссылку можно восстановить до указателя (&v.front()) и, прибавив размер, получить указатель за конец массива (&v.front()+v.size()).
Итератор конца (v.end()) неразыменовываемый, *v.end() — UB. Так что лобовое решение &*v.end() не подходит.

Соответственно, если вектор нулевого размера, v.begin()==v.end(), получить указатель не получится.

Можно, конечно, набраться наглости и сказать v.resize(0); char*p=&v.front(); — но, повторю, это неопределённое поведение. Например, в отладочной версии STL ест шанс схлопотать assert(false).

Но даже если не будет assertion fault, можем получить p==NULL (раз размер нулевой, то внутренний массив не выделен, а внутренние указатели выставлены в некое дефолтное, т.е. нулевое значение).
То есть, указатель для g() будет валидный, неразыменовываемый (а мы и не собирались разыменовывать — n==0), но — нулевой.

Возможно, что g() способно работать и с набором параметров g(NULL,NULL,0). Этого из начальных условий задачи мы не знаем. Поэтому я и предложил трюк с max(n,1).
Тем более, что нагрузка на кучу для new char[0] и new char[1] (внутри vector) — почти одинаковая.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[6]: Тестовое задание C++ win
От: igna Россия  
Дата: 01.12.09 14:15
Оценка: +3
Здравствуйте, Kernan, Вы писали:

K>вот только вопрос есть, тебе на вход приходит 0, а на вход функции g ты передёшь 1. Подмена понятий, однако.


Чья бы корова... В оригинальном примере функция g вызывается и в том случае, если "на вход приходит 0", а в твоем — нет.
Re: Тестовое задание C++ win
От: carpenter Голландия  
Дата: 01.12.09 15:24
Оценка: -1
Здравствуйте, amberovsky, Вы писали:

блин — я вообще слепой — все норм по моему — единтственно — можно труями кэтчами обложить ,
но это уже коде стайлинг



A>
A>Какие проблемы Вы видите в этих фрагментах кода и как предлагаете их решать?
A>1.
A>void g( char *, char *, size_t );
A>void f( size_t n )
A>{
A> char *a = new char[n];
A> char *b = new char[n];
A> g( a, b, n );
A> delete [] b;
A> delete [] a;
A>}

A>2.
A>int main(int argc, char* argv[])
A>{
A> if( argc > 1 )
A>  printf( argv[1] );
A> return 0;
A>}

A>
Весь мир — Кремль, а люди в нем — агенты
Re[7]: Тестовое задание C++ win
От: Kernan Ниоткуда https://rsdn.ru/forum/flame.politics/
Дата: 01.12.09 15:28
Оценка: :)
Здравствуйте, Кодт, Вы писали:

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


K>>вот только вопрос есть, тебе на вход приходит 0, а на вход функции g ты передёшь 1. Подмена понятий, однако. Хотя код неплох, есть чему поучится


К>Если ты присмотришься внимательно, то заметишь: на вход g приходит 0.


К>Но в конструкторы векторов действительно приходит 1. Это нужно затем, чтобы эмулировать поведение new char[0].

К>Дело в том, что char* p = new char[0] — это валидный ненулевой неразыменовываемый (обрати внимание на эти три слова!) указатель за конец массива.

К>Вектор же не оперирует указателями. Он отдаёт итераторы, разыменовывая которые, получаем ссылки (*v.begin()); или же сразу ссылки (v[0], v.front()).

К>Потом ссылку можно восстановить до указателя (&v.front()) и, прибавив размер, получить указатель за конец массива (&v.front()+v.size()).
К>Итератор конца (v.end()) неразыменовываемый, *v.end() — UB. Так что лобовое решение &*v.end() не подходит.

К>Соответственно, если вектор нулевого размера, v.begin()==v.end(), получить указатель не получится.


К>Можно, конечно, набраться наглости и сказать v.resize(0); char*p=&v.front(); — но, повторю, это неопределённое поведение. Например, в отладочной версии STL ест шанс схлопотать assert(false).


К>Но даже если не будет assertion fault, можем получить p==NULL (раз размер нулевой, то внутренний массив не выделен, а внутренние указатели выставлены в некое дефолтное, т.е. нулевое значение).

К>То есть, указатель для g() будет валидный, неразыменовываемый (а мы и не собирались разыменовывать — n==0), но — нулевой.

К>Возможно, что g() способно работать и с набором параметров g(NULL,NULL,0). Этого из начальных условий задачи мы не знаем. Поэтому я и предложил трюк с max(n,1).

К>Тем более, что нагрузка на кучу для new char[0] и new char[1] (внутри vector) — почти одинаковая.
Получается, что ты предполагаешь, что функция g проверяет n >= 0, чего может и не быть. Более того, неизвестный код может длелать какие-то действия в случае (NULL, NULL, 0).
Sic luceat lux!
Re[8]: Тестовое задание C++ win
От: Кодт Россия  
Дата: 01.12.09 16:01
Оценка: +2
Здравствуйте, Kernan, Вы писали:

К>>Возможно, что g() способно работать и с набором параметров g(NULL,NULL,0). Этого из начальных условий задачи мы не знаем. Поэтому я и предложил трюк с max(n,1).

К>>Тем более, что нагрузка на кучу для new char[0] и new char[1] (внутри vector) — почти одинаковая.
K>Получается, что ты предполагаешь, что функция g проверяет n >= 0, чего может и не быть. Более того, неизвестный код может длелать какие-то действия в случае (NULL, NULL, 0).

Я просто предложил наиболее консервативный рефакторинг.
А именно, обеспечил безопасность от исключений на ввереном мне участке, никак не затронув поведение остального кода (ни вызывающего, ни внутри g()).

Единственный упрёк в сторону векторов — то, что чуть-чуть изменяется рисунок стека и кучи. Это может сыграть в условиях стресс-тестирования.
boost::scoped_array — более предпочтительный вариант в этом плане.
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[2]: Тестовое задание C++ win
От: Кодт Россия  
Дата: 01.12.09 16:01
Оценка: +1
Здравствуйте, carpenter, Вы писали:

C>блин — я вообще слепой — все норм по моему — единтственно — можно труями кэтчами обложить ,

C>но это уже коде стайлинг

Угу, слепой Среди 70 ответов выше были разные мнения и советы, и про "не всё норм", и про "можно без try-catch"...
... << RSDN@Home 1.2.0 alpha 4 rev. 1237>>
Перекуём баги на фичи!
Re[8]: Тестовое задание C++ win
От: andrey.desman  
Дата: 01.12.09 16:57
Оценка:
Здравствуйте, Kernan, Вы писали:

K>Получается, что ты предполагаешь, что функция g проверяет n >= 0, чего может и не быть. Более того, неизвестный код может длелать какие-то действия в случае (NULL, NULL, 0).

Может, не может, а вдруг и не так, а сяк. Предположения летят в мусорное ведро. Акстись запускать вот так просто какой-то неизвестный код! Просто смотришь в код функции и видишь что она делает. Или доку читаешь. Или, наконец, просто один раз проверяешь.
Изначальный вопрос — дерьмо, т.к. искать сферические проблемы в сфрическом коде суть занятие бесполезное, потому что проблем можно напридумывать кучу. И спорить кто прав, кто виноват потом можно до усрачки, потому что у одного глаз косит на 30 градусов, а у другого на 17, и никак их точки зрения не совпадут...
А самый главный косяк в изначальном коде — это с особым усердием подобранные, как бы намекающие на всю глупость ситуации, имена функций и переменных. Вот где есть простор для фантазии! Кто какое имя придумает? Устроим знатный holy war!
Re[3]: Тестовое задание C++ win
От: IID Россия  
Дата: 01.12.09 17:26
Оценка:
Здравствуйте, Vamp, Вы писали:

R>>Если вылетит исключение при выделении памяти под b, то память для a не будет освобождена -> утечка память.

V>Ну какая утечка? Если вылетит исключение в приведенном фрагменте, программа просто завершится и всю память почистит ОС.

Почему же ? Окружение, в котором вызывается функция f нам неизвестно. Вполне возможно что там исключение будет перехвачено, и программа нисколько не завершится. Итого: утечка.
kalsarikännit
Re[8]: Тестовое задание C++ win
От: maykie Россия  
Дата: 02.12.09 12:10
Оценка: +1
в g(NULL,NULL,0). Этого из начальных условий задачи мы не знаем. Поэтому я и предложил трюк с max(n,1).
К>>Тем более, что нагрузка на кучу для new char[0] и new char[1] (внутри vector) — почти одинаковая.
K>Получается, что ты предполагаешь, что функция g проверяет n >= 0, чего может и не быть.

Не понял зачем ей это проверять. n всегда >= 0. size_t беззнаковый.
Re[9]: Тестовое задание C++ win
От: Erop Россия  
Дата: 02.12.09 16:39
Оценка:
Здравствуйте, maykie, Вы писали:

M>Не понял зачем ей это проверять. n всегда >= 0. size_t беззнаковый.

Почему size_t всегда должен быть беззнаковым?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[10]: Тестовое задание C++ win
От: igna Россия  
Дата: 02.12.09 16:48
Оценка:
Здравствуйте, Erop, Вы писали:

E>Почему size_t всегда должен быть беззнаковым?



7.17 Common definitions <stddef.h>

. . .


size_t

which is the unsigned integer type of the result of the sizeof operator

(ISO/IEC 9899:1999)

Re[6]: Тестовое задание C++ win
От: alexander_st Россия  
Дата: 02.12.09 20:07
Оценка: :))
Здравствуйте, Кодт, Вы писали:

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


V>>>Вообще-то, никто не мешает вызвать delete для константных указателей.

_>>Уп-с ... правда?
_>>давно последний раз пробовали?

К>Да вот только что: http://codepad.org/9DrfRKDV

Из каких соображений тогда ну скажем ф-я std::string c_str() возвращает const char* а не просто char* ? может для того , что бы показать, что удалять этот буфер не надо?
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.