Здравствуйте, alexander_st, Вы писали:
_>Здравствуйте, Кодт, Вы писали:
К>>Здравствуйте, alexander_st, Вы писали:
V>>>>Вообще-то, никто не мешает вызвать delete для константных указателей. _>>>Уп-с ... правда? _>>>давно последний раз пробовали?
К>>Да вот только что: http://codepad.org/9DrfRKDV _>Из каких соображений тогда ну скажем ф-я std::string c_str() возвращает const char* а не просто char* ? может для того , что бы показать, что удалять этот буфер не надо?
Нет, для того, чтобы показать что этот буфер изменять не надо.
Здравствуйте, amberovsky, Вы писали:
A>В итоге мне отказали. A>В чём я ошибся или чего важного не указал?
1.
void g( char *, char *, size_t );
Функция совершенно непонятно что делает? функцию с именем g и без коментария необходимо переписать.
void f( size_t n )
Кроме описанного выше, нет контроля за удалением памяти при возникновении исключения, плюс если нет специальных требований, следует использовать безопасные массивы.
2. Без указания спецификаций непонятно о чем говорить. Использование специальных символов может быть by design, важной фичей.
Здравствуйте, Smal, Вы писали:
S>Нет, для того, чтобы показать что этот буфер изменять не надо.
из каких соображений? что будет если его изменить?.... точнее чем изменение буфера хуже его удаления?
Здравствуйте, alexander_st, Вы писали:
_>Из каких соображений тогда ну скажем ф-я std::string c_str() возвращает const char* а не просто char* ? может для того , что бы показать, что удалять этот буфер не надо?
Знаешь, есть дофига способов abuse. Например, получить указатель на неконстантный объект в стеке или статике — и попробовать его удалить. И никто не пикнет, кроме менеджера кучи перед смертью.
Ещё можно попробовать удалить delete[] &vec.front() — вполне себе неконстантный массив, рамещённый на куче... Ты просто украдёшь право владения, которое было у вектора.
Язык С++ в явном виде не декларирует права владения указуемыми объектами. Иначе бы указатель на стековый объект и указатель на объект, созданный на куче, должны были быть разного типа!!!
Это можно только гигиеной и дисциплиной обеспечить. Гигиена — это, как минимум, умными указателями с политиками.
Беда в том, что голый указатель предоставляет сразу все права (ну только с константностью есть ограничение на изменение объекта). А следовательно, всегда остаётся возможность для нецелевого использования. А следовательно — без дисциплины никуда.
Здравствуйте, minorlogic, Вы писали:
M>2. Без указания спецификаций непонятно о чем говорить. Использование специальных символов может быть by design, важной фичей.
При использовании %s printf будет пытаться вытаскивать из стека указатели на строки (которые туда никто не клал). Как минимум это UB, и будет печататься мусор, как максимум — в случае более сложной программы можно анализировать стек и вытаскивать какие то, возможно, важные данные.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, alexander_st, Вы писали:
_>>Из каких соображений тогда ну скажем ф-я std::string c_str() возвращает const char* а не просто char* ? может для того , что бы показать, что удалять этот буфер не надо?
К>Знаешь, есть дофига способов abuse. Например, получить указатель на неконстантный объект в стеке или статике — и попробовать его удалить. И никто не пикнет, кроме менеджера кучи перед смертью. К>Ещё можно попробовать удалить delete[] &vec.front() — вполне себе неконстантный массив, рамещённый на куче... Ты просто украдёшь право владения, которое было у вектора.
К>Язык С++ в явном виде не декларирует права владения указуемыми объектами. Иначе бы указатель на стековый объект и указатель на объект, созданный на куче, должны были быть разного типа!!! К>Это можно только гигиеной и дисциплиной обеспечить. Гигиена — это, как минимум, умными указателями с политиками. К>Беда в том, что голый указатель предоставляет сразу все права (ну только с константностью есть ограничение на изменение объекта). А следовательно, всегда остаётся возможность для нецелевого использования. А следовательно — без дисциплины никуда.
это все хорошо и правильно, но увы, даже на 1% не отвечает на мой вопрос
Здравствуйте, alexander_st, Вы писали:
_>это все хорошо и правильно, но увы, даже на 1% не отвечает на мой вопрос
Потому что ты упорно задаёшь свой вопрос как риторический.
Буквальный ответ про string: она возвращает указатель на массив из константных элементов, чтобы никто не мог изменять значения этих элементов.
При этом подразумевается, что массивом владеют только объекты string. Какое там владение: монопольное или разделяемое (когда несколько объектов пользуются общим массивом, идиома COW) — для пользователя не имеет значения. НЕ ЕГО СОБАЧЬЕ ДЕЛО.
Это подразумевание запрещает управлять памятью извне. И более того, если программист не враг себе, он не имеет права управлять никакой памятью, которая ему не отдана во владение.
Здравствуйте, Vamp, Вы писали:
К>>Проблема в том, что задание провалено. V>Я не думаю, что это проблема . Работать в организации, предлагающей такие задания как дистанционное — верный путь в никуда. Очевидно, что задание предполагает тщательное обсуждение с кандидатом после ЛЮБОГО его ответа.
Да ладно тебе. Две элементарные задачи и ни одного правильного ответа. Почему здесь нужно тщательное обсуждение? Тем более задача решается удалённо, никто никого не торопит.
Я знаю только две бесконечные вещи — Вселенную и человеческую глупость, и я не совсем уверен насчёт Вселенной. (c) А. Эйнштейн
P.S.: Винодельческие провинции — это есть рулез!
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>
Не вижу ни малейшей проблемы в этом примере. Точнее сказать так — все зависит от контекста применения. А контекста нету. Бывают, например, случаи, когда исключения вообще запрещены. И если new может венуть 0, а в g() это обрабатывается, то даный код полностью легален. Например, я вообще вынужден пользоваться longjmp, когда память кончается — А что поделаешь на Sony PS3 Cell? — исключения сразу раздувают код процентов на 30, а там — каждый килобайт на счету. Ну и гадость же этот cell оказался, сплошной рак головы. Ждем интел лараби с его кэш-когерентностью (если дождемся, конечно).
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Здравствуйте, Vamp, Вы писали:
_>>а если эта ф-я экспортируется из dll она бы тоже принимала 2 вектора? V>Дело не в экспорте, а в языке. Зачем С++ функции принимать указатели, если можно векторы?
_>>а исключение по выделению памяти или по какому нить доступу по кривому указателю она тоже не может кинуть? V>С++ исключение, если она написана на С — не может.
Здравствуйте, Vamp, Вы писали:
К>>Незнание законов не освобождает от ответственности. Раз есть new, значит, есть и std::bad_alloc. V>Где? В вызывающей функции он есть. Но я вообще-то не считаю, что bad_alloc надо перехватывать, за исключением редких стратегий типа — попросим 10 гиг, не получилось — тогда 5, опять не получилось, тогда 2 Кб. Как правило, программа просит столько памяти, сколько ей надо для работы, и ничего осмысленного после bad_alloc сделать не сможет. Более того, в ситуации тотальной нехватки вполне возможно, что даже диагностические сообщения вывести не удастся, так что пусть уж честно рушится. По крайней мере, в тех же Unix будет вполне читабельная корка.
Похоже, ты никогда не видел переопределенного new. Который например, может брать память из какого-нибудь ограниченного по размеру блока, отображенного файла и вообще хз откуда. И даже наличие свободного гига еще совсем не значит, что malloc на гиг будет успешным — фрагментацию пока никто не отменял! Нет никакой гарантии, что ОС справится с фрагментацией!
И даже при стандартном new в ответ на bad_alloc еще много чего можно сделать. Например, если не получилось выполнить текущую задачу в списке — можно просто ее не выполнить и перейти к следующей.
Здравствуйте, McSeem2, Вы писали:
MS>Не вижу ни малейшей проблемы в этом примере. Точнее сказать так — все зависит от контекста применения. А контекста нету. Бывают, например, случаи, когда исключения вообще запрещены. И если new может венуть 0, а в g() это обрабатывается, то даный код полностью легален.
А такой new так же пишется?
Насколько можно понять, тест на знание _современного_ С++?
Здравствуйте, любой, Вы писали:
Л>Здравствуйте, amberovsky, Вы писали:
Л>Тут по существу уже сказали. А меня в таком коде всегда прикалывает, почему два блока нельзя за раз выделить:
Л>char *a = new char[n*2]; Л>char *b = a + n; Л>g( a, b, n ); Л>delete [] a;
Насколько я понимаю в этом случае нужен будет в два раза больший непрерывный блок памяти, который найти меньше шансов, чем два поменьше
Здравствуйте, Tesh, Вы писали:
Л>>char *a = new char[n*2]; Л>>char *b = a + n; Л>>g( a, b, n ); Л>>delete [] a;
T>Насколько я понимаю в этом случае нужен будет в два раза больший непрерывный блок памяти, который найти меньше шансов, чем два поменьше
Зато в сумме потребуется чуть меньше памяти, т.к. накладные расходы на один блок меньше.