R>Если вылетит исключение при выделении памяти под b, то память для a не будет освобождена -> утечка память.
Ну какая утечка? Если вылетит исключение в приведенном фрагменте, программа просто завершится и всю память почистит ОС.
Здравствуйте, Кодт, Вы писали:
К>Здравствуйте, amberovsky, Вы писали:
A>>1. new может не сработать, нужно добавить, например, try/catch. К>Лучше не try-catch (это слишком громоздко), а RAII — любой умный указатель или контейнер. К>Паранойя. Чтобы испортить указатели, функция должна расстрелять стек. А это никакими средствами не лечится.
чтобы испортить указатели ф-я не должна стрелять в стек, она должна всего лишь вызвать для них delete и лечится это передачей константных указателей
то биш
g(const char*, const char*, size_t);
только не надо предположений что можно сделать всякие const_cast`ы и спецом все на свете по удалять, вот это уже действительно паранойя
К>Решение К>
К>void f(size_t n)
К>{
К> if(n!=0)
К> {
К> std::vector<char> a(n), b(n);
К> g(&a.front(), &b.front(), n);
К> }
К> else// если мы ничего не знаем про логику g(), попробуем максимально близко воспроизвести ситуацию
К> {
К> char a,b;
К> g(&a,&b,0); // передаём два уникальных ненулевых адреса! ибо new char[0] != NULL
К> // хотя, возможно, было бы достаточно
К> g(NULL,NULL,0);
К> }
К> // или, в обобщённом виде
К> std::vector<char> a(max(n,1)), b(max(n,1)); // гарантируем непустоту и уникальность
К> g(&a.front(), &b.front(), n);
К>}
К>
чем в данном контексте использование std::vector лучше, чем непосредственный указатели? К>А вот метнуть исключение функция g() может запросто.
но в вашем коде так же нет защиты от метания исключений
К>А вот метнуть исключение функция g() может запросто.
А вот это маловероятно. Сигнатура функции предполагает, что она написана не на С++, а на С. А значит, скорее всего, никаких исключений она бросить не может.
И по большому счету, я вижу реальную проблему только в printf.
_>чтобы испортить указатели ф-я не должна стрелять в стек, она должна всего лишь вызвать для них delete и лечится это передачей константных указателей
Вообще-то, никто не мешает вызвать delete для константных указателей.
Здравствуйте, Vamp, Вы писали:
К>>А вот метнуть исключение функция g() может запросто. V>А вот это маловероятно. Сигнатура функции предполагает, что она написана не на С++, а на С. А значит, скорее всего, никаких исключений она бросить не может.
Здравствуйте, amberovsky, Вы писали:
A>Здравствуйте, SaZ, Вы писали:
SaZ>>Если задание удалённое — то неправильно. А на собеседовании попросили бы аргументировать. Почему — написано ниже.
A>Вы считаете ошибку со слешем причиной отказать?
Не только в слэше делать, но зачем вспоминать, если не уверен в правильности? Вспомнился случай с одного экзамена, когда преподаватель как раз подобными вопросами всех валил. А причина была простая: непонимание группой того, что \n — это один символ, понятный лишь компилятору и не принимаемый извне.
Признаю, что возможно немного погорячился с оценкой. Цепляться в этом случае или нет, так сказать, человеко-зависимо. Мои преподаватели бы зацепились (на собеседовании, а на экзамене — тем более).
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>
инициализация строк, какой нить const char* или std::string в параметрах g и то, что по хорошему надо в g передать 2 размера, а не один (если это не strcpy )..
также, как вариант ответа, сойдёт "этот код хз что делает, поэтому его надо переписать по человечески"..
Здравствуйте, amberovsky, Вы писали:
A>Здравствуйте. A>При попытке устроится в одну фирму прислали "удалённое" тестовое задание.
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>
void g( const char *, const char *, size_t );
void f( size_t n )
{
сhar *a = NULL;
char *b = NULL;
if (n <= 0)
return;
try
{
a = new char[n];
b = new char[n];
g( a, b, n );
}
catch (...)
{
if (a) delete [] a;
if (b) delete [] b;
}
if (a) delete [] a;
if (b) delete [] b;
}
какие авто_птр?? какой буст??? Зачем усложнять жизнь в тривиальном куске кода? KISS!
A>
A>2.
A>int main(int argc, char* argv[])
A>{
A> if( argc > 1 )
A> printf( argv[1] );
A> return 0;
A>}
A>
Не смущает, что нумерация массива начинается с 0, и в argc[0] == 'имя исполняемого файла'?
Т.е. argc всегда > 0
R>>>void f( size_t n )
R>>>{
R>>> std::auto_ptr<char> a (new char[n]);
R>>> std::auto_ptr<char> b (new char[n]);
R>>> g( a.get(), b.get(), n );
R>>>}
I>
S>>Тут UB. I>Почему?
Потому что auto_ptr будет удалять память delete'ом без скобок.
Здравствуйте, igna, Вы писали:
I>Здравствуйте, Smal, Вы писали:
I>
R>>>void f( size_t n )
R>>>{
R>>> std::auto_ptr<char> a (new char[n]);
R>>> std::auto_ptr<char> b (new char[n]);
R>>> g( a.get(), b.get(), n );
R>>>}
I>
S>>Тут UB.
I>Почему?
Потому что auto_ptr::~auto_ptr вызывает delete, а не delete [].
Вызов непарного "delete-expression" == UB :
5.3.5 Delete [expr.delete]
1.
The delete-expression operator destroys a most derived object (1.8) or array created by a new-expression.
The first alternative is for non-array objects, and the second is for arrays. Whenever the delete keyword is immediately
followed by empty square brackets, it shall be interpreted as the second alternative.72) The operand shall have a pointer
type, or a class type having a single non-explicit conversion function (12.3.2) to a pointer type. The result has type void.
2.
If the operand has a class type, the operand is converted to a pointer type by calling the above-mentioned conversion
function, and the converted operand is used in place of the original operand for the remainder of this section. In either
alternative, the value of the operand of delete may be a null pointer value. If it is not a null pointer value, in the first
alternative (delete object), the value of the operand of delete shall be a pointer to a non-array object or a pointer to a
subobject (1.8) representing a base class of such an object (clause 10). If not, the behavior is undefined. In the second
alternative (delete array), the value of the operand of delete shall be the pointer value which resulted from a previous
array new-expression.73) If not, the behavior is undefined. [ Note: this means that the syntax of the delete-expression
must match the type of the object allocated by new, not the syntax of the new-expression. —end note ] [ Note: a pointer
to a const type can be the operand of a delete-expression; it is not necessary to cast away the constness (5.2.11) of the
pointer expression before it is used as the operand of the delete-expression. —end note ]
...
Здравствуйте, Vamp, Вы писали:
SC>>Каким образом она это указывает? V>Способом передачи параметров. Если бы она была написана на С++, она бы принимала два вектора.
а если эта ф-я экспортируется из dll она бы тоже принимала 2 вектора?
а исключение по выделению памяти или по какому нить доступу по кривому указателю она тоже не может кинуть?
_>а если эта ф-я экспортируется из dll она бы тоже принимала 2 вектора?
Дело не в экспорте, а в языке. Зачем С++ функции принимать указатели, если можно векторы?
_>а исключение по выделению памяти или по какому нить доступу по кривому указателю она тоже не может кинуть?
С++ исключение, если она написана на С — не может.