Re: Тестовое задание C++ win
От: duncanmclaud  
Дата: 24.12.09 14:04
Оценка:
Здравствуйте, 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>2.
A>int main(int argc, char* argv[])
A>{
A> if( argc > 1 )
A>  printf( argv[1] );
A> return 0;
A>}

A>


A>Я ответил так:

A>1. new может не сработать, нужно добавить, например, try/catch. Кроме того, g может "испортить" указатели (как тут просто решить я не знаю)
A>2. В аргументе командной строки может встретиться символ % или \, что будет расценено printf как специальный символ.
A>Если следующие символы совпадут с какой-либо спецификацией формата (для % или \), то в данном случае для % — UB, для \ — произойдёт подстановка.
A>Решение — printf("%s", argv[1]);
A>Ещё можно проверить что printf действительно напечатало нужное количество символов.


A>В итоге мне отказали.

A>В чём я ошибся или чего важного не указал?



void g( char *, char *, size_t)
{
}

void f( size_t n )
{
char *a = new(nothrow) char[n];
char *b = new(nothrow) char[-n];// если не возможно выделить память, как в данном случае, не генерит эксепшн, просто возвращает 0.

if(a && b)
{
g( a, b, n );
}

if(b)
{
delete [] b;
b = 0;
}

if(a)
{
delete [] a;
a = 0;
}
}
Re: Тестовое задание C++ win
От: duncanmclaud  
Дата: 24.12.09 14:07
Оценка:
Здравствуйте, 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>2.
A>int main(int argc, char* argv[])
A>{
A> if( argc > 1 )
A>  printf( argv[1] );
A> return 0;
A>}

A>


A>Я ответил так:

A>1. new может не сработать, нужно добавить, например, try/catch. Кроме того, g может "испортить" указатели (как тут просто решить я не знаю)
A>2. В аргументе командной строки может встретиться символ % или \, что будет расценено printf как специальный символ.
A>Если следующие символы совпадут с какой-либо спецификацией формата (для % или \), то в данном случае для % — UB, для \ — произойдёт подстановка.
A>Решение — printf("%s", argv[1]);
A>Ещё можно проверить что printf действительно напечатало нужное количество символов.


A>В итоге мне отказали.

A>В чём я ошибся или чего важного не указал?


void g( char *, char *, size_t)
{
}

void f( size_t n )
{
char *a = new(nothrow) char[n];
char *b = new(nothrow) char[-n]; // если память не возможно выделить, как в данном случае, эксепшена не будет, возвратится 0

if(a && b)
{
g( a, b, n );
}

if(b)
{
delete [] b;
b = 0;
}

if(a)
{
delete [] a;
a = 0;
}
}
Re[5]: Тестовое задание C++ win
От: KoriBRand  
Дата: 26.12.09 13:17
Оценка: -4 :)
Здравствуйте, SergeyT., Вы писали:

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


S>>>Ну, тогда уж

S>>>
S>>>void f( size_t n )
S>>>{
S>>> std::vector<char> a (n);
S>>> std::vector<char> b (n);
S>>> g( &a[0], &b[0], n );
S>>>}
S>>>


ST>Это не очень красивая, но совершенно стандартная идиома.

ST>Скотт Мейерс, Эффективное использование STL, Item 16

Ну нахрен такие идиомы. Добавишь ты в вектор новый элемент, сделает он реаллокацию внутреннего буфера, и указатель, который передавался в doSomething станет невалидным. А функция могла его где-нибудь сохранить. Конечно, как правило такой сценарий или не возникает или ничем не грозит, но один раз из ста, когда грабли срабатывают, бывает достаточно неприятным.
offtop
Re[7]: Тестовое задание C++ win
От: Roman Odaisky Украина  
Дата: 26.12.09 18:53
Оценка:
Здравствуйте, Vamp, Вы писали:

V>Дело не в экспорте, а в языке. Зачем С++ функции принимать указатели, если можно векторы?


Было — void g(char *, std::size_t).

Стало — void g(std::vector<char, а здесь что?> &).
До последнего не верил в пирамиду Лебедева.
Re[4]: Тестовое задание C++ win
От: tealex  
Дата: 30.12.09 00:12
Оценка: +1
видимо для отсева работодателя )
хана
Re: Тестовое задание C++ win
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 11.01.10 14:08
Оценка: :)
Здравствуйте, amberovsky, Вы писали:

A>При попытке устроится в одну фирму прислали "удалённое" тестовое задание.


1. Какие проблемы Вы видите в этих фрагментах кода


2. Как предлагаете их решать?

Вычислить автора и фтопку его.

А так же всех, кто сидел слева и справа от него — вдруг они уже заразились ...

-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[6]: Тестовое задание C++ win
От: Zhendos  
Дата: 13.01.10 12:30
Оценка:
Здравствуйте, KoriBRand, Вы писали:

KBR>Здравствуйте, SergeyT., Вы писали:


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


S>>>>Ну, тогда уж

S>>>>
S>>>>void f( size_t n )
S>>>>{
S>>>> std::vector<char> a (n);
S>>>> std::vector<char> b (n);
S>>>> g( &a[0], &b[0], n );
S>>>>}
S>>>>


ST>>Это не очень красивая, но совершенно стандартная идиома.

ST>>Скотт Мейерс, Эффективное использование STL, Item 16

KBR>Ну нахрен такие идиомы. Добавишь ты в вектор новый элемент, сделает он реаллокацию внутреннего буфера, и указатель, который передавался в doSomething станет невалидным.


вообще-то данный пример изначально выглядел как

p = new
doSomething
delete p


если doSomething сохраняет и при повторных вызовах его использует, то будет такая же проблема
что и с vector,
в чем смысл вашего возражения?
Re: Тестовое задание C++ win
От: KhConstantine Россия  
Дата: 02.05.10 14:47
Оценка:
Здравствуйте, amberovsky, Вы писали:

A>Здравствуйте.

A>При попытке устроится в одну фирму прислали "удалённое" тестовое задание.
Мне пришло такое задание от DrWeb. Кто-то еще так развлекается?
В общем, побывал я в DrWeb на собеседовании и даю правильный с их точки зрения ответ:
По первому заданию:

void f_drWeb( size_t n )
{
     using namespace std;
     vector<char> a (n), b(n);
     g( &a[0], &b[0], n );
     cout<<endl<<"func f_drWeb said:"<<"a="<<&a[0]<<" b="<<&b[0];
};



По второму заданию:



int main(int argc, char* argv[])
{
    const char *locId="Russian";
    // Для C
    if(argc>1)
    {
        printf("\n printf said: %s", argv[1]);
        setlocale(LC_ALL, "Russian"); // "Russian" - для винды и русского. Это необходимо для C, 
                                      // но недостаточно для wcout
    }      

    //Для потоков
    locale loc(locId);
      locale::global(loc); // Это необходимо для wcout(setlocale недостаточно).
    wcout.imbue(loc);    // Применяем к wcout, потому что wcout УЖЕ открыт. Действует и на stdout
                         // так что в принципе можно обойтись и без setlocale
    if(argc>1)
    {
        wcout<<endl<<"wcout said:"<<argv[1];
    };
return 0;
}



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>



Кроме того, можете скачать http://piterludi.com/fordeveloponbox/stlfuns.zip
В этом проекте (VC++ 2008) я продемонстрировал также поведение виртуальных функций, вызываемых из конструкторов и деструкторов — вопрос,
который почему-то нередко возникает на собеседованиях. Также немного побаловался с промышленным дизайном для этой же задачи.
Хотя по ходу собеседования я и сделал вывод, что промышленный дизайн и общепринятые подходы они считают
ненужным усложнением и ретроградством.

Возможно, я ошибаюсь: все-таки собеседование проходило в стиле "опусти кандидата",
а при таком стиле язвительно критикуется любое высказывание.
Вероятно, предполагается, что осознавший свое ничтожество и полностью дезориентированный кандидат
преисполнится безумной радости, если ему все-таки сделают предложение поработать в такой новаторской фирме.
Просто держите в голове, что "опустить" можно любого: конкретно моих "экзаменаторов" можно было бы легко "опустить" как минимум
по знаниям паттернов проектирования (особенно сoncurrency) и подходам к разработке сложных систем. Никто не может знать всего.

Если будете у них на собеседовании — в момент, когда от вас потребуют что-либо написать, постарайтесь не отвлекаться
на вопросы "экзаменаторов", "заторапливание" и попытки вывести вас из себя. Иначе наделаете таких ляпов, что самому потом будет стыдно.
Re[2]: Тестовое задание C++ win
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 02.05.10 14:57
Оценка:
Здравствуйте, KhConstantine, Вы писали:

KC> я продемонстрировал также поведение виртуальных функций, вызываемых из конструкторов и деструкторов — вопрос,

KC>который почему-то нередко возникает на собеседованиях.

Больная тема, наверное....

К примеру — в последнее время мой IE8 стал слишком часто говорить "pure virtual что-то там call"
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[3]: Тестовое задание C++ win
От: KhConstantine Россия  
Дата: 02.05.10 17:42
Оценка:
Здравствуйте, Коваленко Дмитрий, Вы писали:

КД>К примеру — в последнее время мой IE8 стал слишком часто говорить "pure virtual что-то там call"

Очень интересно... Потому что именно MSVC вроде бы матерится на это на этапе ЛИНКОВКИ, а не рантайма...
Мне тоже на одном из собеседований утверждали, что маты идут на этапе рантайма, причем с именно MS.
Интересно было бы пример посмотреть — в реальной жизни я с таким не встречался.
А вот в архиве, на который я сделал ссылку,этот кусочек — как раз на линковке валится:

stlfuns_main.obj : error LNK2001: unresolved external symbol "public: virtual void __thiscall AGFuncCaller::dump(void)" (?dump@AGFuncCaller@@UAEXXZ)
D:\experiments\stlfuns\Debug\stlfuns.exe : fatal error LNK1120: 1 unresolved externals

// базовый для всех объектов, работающих с G
// в том числе и для тех, которым данные из буфера нужны
class AGFuncCaller
{    
........        
            
        AGFuncCaller(SomeSubSystem &oSomeSubSystem)
        {
            //dump(); // uncomment it to see the LINKER (not real-time) problem of calling 
                    //abstract virtual function
            gBufferSize     = 0;                    
            _oSomeSubSystem = &oSomeSubSystem;
            getSubSystem()->log("1. Constructor AGFuncCaller said:");
            someVirtualFunc();
            getSubSystem()->log("1. Constructor AGFuncCaller finishing");
        };

......        
        virtual void dump()=0;
......
};
Re[4]: Тестовое задание C++ win
От: Alexey F  
Дата: 02.05.10 18:42
Оценка:
Здравствуйте, KhConstantine, Вы писали:

КД>>К примеру — в последнее время мой IE8 стал слишком часто говорить "pure virtual что-то там call"

KC>Очень интересно... Потому что именно MSVC вроде бы матерится на это на этапе ЛИНКОВКИ, а не рантайма...
KC>Мне тоже на одном из собеседований утверждали, что маты идут на этапе рантайма, причем с именно MS.
KC>Интересно было бы пример посмотреть — в реальной жизни я с таким не встречался.
KC> А вот в архиве, на который я сделал ссылку,этот кусочек — как раз на линковке валится:

А так? (MS VC под рукой нет, поэтому GCC; через промежуточную функцию ):
class Base {
public:
    Base () {
        anotherFunction ();
    }
    
    
    void anotherFunction () {
        pure ();
    }
    
    
    virtual void pure () = 0;
};


class Derived : public Base {
public:
    virtual void pure () {
        return;
    }
};


int main () {
    Derived derived;
}


Результат:

pure virtual method called
terminate called without an active exception

This application has requested the Runtime to terminate it in an unusual way.
Please contact the application's support team for more information.

Re[4]: Тестовое задание C++ win
От: Вертер  
Дата: 02.05.10 20:10
Оценка:
КД>>К примеру — в последнее время мой IE8 стал слишком часто говорить "pure virtual что-то там call"
KC>Очень интересно... Потому что именно MSVC вроде бы матерится на это на этапе ЛИНКОВКИ, а не рантайма...

везёт же некоторым , а вот кто работал с Visual Studio 6.0 знает, что компилятор гордо промолчит и даже никакого warning не будет на 4м уровне.

Во всех последующих версиях студии, генерится ошибка на этапе компиляции.
Re[9]: Тестовое задание C++ win
От: Юрий Жмеренецкий ICQ 380412032
Дата: 03.05.10 05:37
Оценка:
Здравствуйте, Кодт, Вы писали:

К>boost::scoped_array — более предпочтительный вариант в этом плане.


В C++0x можно обойтись без буста: 'std::unique_ptr<char[]>'.
Re[5]: Тестовое задание C++ win
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 03.05.10 11:07
Оценка:
Здравствуйте, Вертер, Вы писали:

КД>>>К примеру — в последнее время мой IE8 стал слишком часто говорить "pure virtual что-то там call"


В>везёт же некоторым , а вот кто работал с Visual Studio 6.0 знает, что компилятор гордо промолчит и даже никакого warning не будет на 4м уровне.


Навеяло:
— "Предлагаю сразу перейти к третьей степени устрашения. У нас даже генералы плачут как дети."
— "Разрешите присутствовать?!"

Шматрица.
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[4]: Тестовое задание C++ win
От: Коваленко Дмитрий Россия http://www.ibprovider.com
Дата: 03.05.10 11:27
Оценка:
Здравствуйте, KhConstantine, Вы писали:

КД>>К примеру — в последнее время мой IE8 стал слишком часто говорить "pure virtual что-то там call"

KC>Очень интересно... Потому что именно MSVC вроде бы матерится на это на этапе ЛИНКОВКИ, а не рантайма...

здесь
Автор: Коваленко Дмитрий
Дата: 05.05.06
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Re[5]: Тестовое задание C++ win
От: slava_phirsov Россия  
Дата: 04.05.10 06:24
Оценка:
Здравствуйте, Alexey F, Вы писали:

AF>А так? (MS VC под рукой нет, поэтому GCC; через промежуточную функцию ):

AF>
AF>class Base {
AF>public:
AF>    Base () {
AF>        anotherFunction ();
AF>    }
    
    
AF>    void anotherFunction () {
AF>        pure ();
AF>    }
    
    
AF>    virtual void pure () = 0;
AF>};


AF>class Derived : public Base {
AF>public:
AF>    virtual void pure () {
AF>        return;
AF>    }
AF>};


AF>int main () {
AF>    Derived derived;
AF>}
AF>


Давно известно, что вызов виртуальной функции в конструкторе в C++ — А-ТА-ТА, в отличие, кстати, от ныне полупокойной Delphi. Еще одна веревка для отстрела собственных конечностей, которых в C++, увы (ура?) хватает.
Люди! Люди, смотрите, я сошел с ума! Люди! Возлюбите друг друга! (вы чувствуете, какой бред?)
Re[5]: Тестовое задание C++ win
От: March_rabbit  
Дата: 04.05.10 08:13
Оценка:
Здравствуйте, igna, Вы писали:

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


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


I>catch, который ловит что попало и это "что попало" затем не перебрасывает, тоже лучше убрать.

здесь у catch есть одна задача: остановить бабах и дать возможность процедуре восстановиться после него.
Так что, пусть постоит....
Re: Тестовое задание C++ win
От: March_rabbit  
Дата: 04.05.10 08:19
Оценка:
Здравствуйте, amberovsky, Вы писали:

A>Я ответил так:

A>1. new может не сработать, нужно добавить, например, try/catch.
Думаю, чисто теоретически это все правильно. Но на практике я бы не сильно заморачивался спецзащитой. Ибо нехватка памяти — это конец. Поймаешь здесь — стрельнет в другом месте (где-нить в stdlib).

За 10 лет программерства ни разу не столкнулся с нехваткой памяти под программу на i386. Один раз сделал утечку, система (Linux) умерла в муках, но не призналась.
Re[2]: Тестовое задание C++ win
От: sergey_cheban  
Дата: 04.05.10 19:08
Оценка: 1 (1) +1 :)))
Здравствуйте, Константин.

KC>В общем, побывал я в DrWeb на собеседовании и даю правильный с их точки зрения ответ:

KC>По первому заданию:
Я рад, что обсуждение недостатков Вашего первоначального ответа пошло Вам на пользу. И всё же:
1. Хочу предостеречь от использования &a[0] без проверки на наличие в векторе хоть каких-то данных. Если мы не предупредили Вас об этой проблеме на собеседовании, это не значит, что её не существует.
2. Вся строчка "func f_drWeb said:" — это Ваши личные фантазии, к которым компания DrWeb не имеет ни малейшего отношения. Пусть они остаются на Вашей совести.

KC>По второму заданию:

Ваши упражнения с локалью пригодны только для одного случая: когда консольная программа вызывается с русскими аргументами в кодировке ANSI. Для случая "консольная программа вызывается из консоли" установка локали создаёт проблемы, а не решает их. На собеседовании Ваш ответ на этот вопрос вообще не обсуждался, и поэтому Ваши утверждения о причастности компании DrWeb к этому коду я решительно отвергаю.

KC>Кроме того, можете скачать http://piterludi.com/fordeveloponbox/stlfuns.zip

KC>В этом проекте (VC++ 2008) я продемонстрировал также поведение виртуальных функций, вызываемых из конструкторов и деструкторов — вопрос,
KC>который почему-то нередко возникает на собеседованиях. Также немного побаловался с промышленным дизайном для этой же задачи.
Вот этот фрагмент особенно порадовал:
void GFuncCaller_NOSTL::clearBuff()
{
        if(!BufferA) delete[] BufferA;// Это не защита. Если BufferA==NULL, проблем с deleteA все равно нет
        BufferA = NULL;                // просто незачем вызывать delete

        if(!BufferB) delete[] BufferB;
        BufferB = NULL;
        
        gBufferSize = 0;
};

У Вас действительно есть свой стиль написания кода. Вы только с названием стиля ошиблись: это не Industrial, а Trash.

KC>Хотя по ходу собеседования я и сделал вывод, что промышленный дизайн и общепринятые подходы они считают

KC>ненужным усложнением и ретроградством.
KC>Возможно, я ошибаюсь: все-таки собеседование проходило в стиле "опусти кандидата",
KC>а при таком стиле язвительно критикуется любое высказывание.
У нас во время собеседования действительно возникли разногласия в том, какие подходы считать общепринятыми. Но не более того.
Что касается стиля "опусти кандидата" — мы честно высказывали своё мнение о Ваших высказываниях и честно давали Вам возможность отстоять свою позицию по тем вопросам, по которым мы были с Вами не согласны.
А вот, например, по второму вопросу из письменного задания мы Вас не "опускали", и вот Вы уже рассказываете, что это и есть правильный, по нашему мнению, вариант.

KC>Вероятно, предполагается, что осознавший свое ничтожество и полностью дезориентированный кандидат

KC>преисполнится безумной радости, если ему все-таки сделают предложение поработать в такой новаторской фирме.
Пожалуйста, воздержитесь от обобщений. К нам и нормальные кандидаты приходят.

KC>Просто держите в голове, что "опустить" можно любого: конкретно моих "экзаменаторов" можно было бы легко "опустить" как минимум

KC>по знаниям паттернов проектирования (особенно сoncurrency) и подходам к разработке сложных систем.
Вы говорите это после того, как сами на собеседовании продемонстрировали незнание http://en.wikipedia.org/wiki/Reactor_pattern? И Вам не стыдно?

KC>Никто не может знать всего.

Этого мы от кандидатов и не требуем.

KC>Если будете у них на собеседовании — в момент, когда от вас потребуют что-либо написать, постарайтесь не отвлекаться

KC>на вопросы "экзаменаторов", "заторапливание" и попытки вывести вас из себя. Иначе наделаете таких ляпов, что самому потом будет стыдно.
...И постарайтесь не тратить по двадцать минут на вопросы типа "Эту задачу можно решить всего тремя строчками кода, а не тридцатью, как Вы предложили. Вы можете написать эти три строчки?".
Re[2]: Тестовое задание C++ win
От: IROV..  
Дата: 04.05.10 22:27
Оценка:
Здравствуйте, Кодт, Вы писали:

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


A>>1. new может не сработать, нужно добавить, например, try/catch.

К>Лучше не try-catch (это слишком громоздко), а RAII — любой умный указатель или контейнер.
Который будет врапером над try-catch?

A>> Кроме того, g может "испортить" указатели (как тут просто решить я не знаю)

К>Паранойя. Чтобы испортить указатели, функция должна расстрелять стек. А это никакими средствами не лечится.
К>А вот метнуть исключение функция g() может запросто.
А еще сигнатура функции может принимать ссылку на указатель и творить с ним все что захочет
я не волшебник, я только учусь!
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.