# V623. Temporary object is created and then destroyed. Consider inspecting the '?:' operator.

Анализатор обнаружил возможную ошибку при работе с тернарным оператором '?:'. Если при работе с оператором '?:' совместно используются объект типа класс и любой другой тип, который может быть преобразован к данному классу, то создаются временные объекты. Временные объекты будут удалены по завершению оператора '?:'. Ошибка возникает, если мы при этом сохраняем результат в переменную типа указатель.

Рассмотрим пример:

    CString s1(L"1");
    wchar_t s2[] = L"2";
    bool a = false;
    ...
    const wchar_t *s = a ? s1 : s2;

В результате выполнения этого кода переменная 's' будет указывать на данные, находящиеся внутри временного объекта. Беда в том, что этот объект уже уничтожен!

Корректный вариант кода:

    wchar_t s1[] = L"1";
    wchar_t s2[] = L"2";
    bool a = false;
    ...
    const wchar_t *s = a ? s1 : s2;

Другой вариант корректного кода:

    CString s1(L"1");
    wchar_t s2[] = L"2";
    bool a = false;
    ...
    CString s = a ? s1 : s2;

Предупреждение V623 требует со стороны программиста повышенного внимания. Беда в том, что ошибки данного типа хорошо прячутся. Код, содержащий подобные ошибки может успешно работать многие годы. Но это только иллюзия, что он работает. На самом деле используется освобождённая память. То, что в памяти находятся корректные данные - это только везение. Поведение программы может поменяться в любой момент. Это может произойти при смене версии компилятора. Это может произойти, после рефакторинга кода, когда появляется новый объект, использующий ту же область памяти. Рассмотрим это на примере.

Напишем, скомпилируем и запустим следующий код:

    bool b = false;
    CComBSTR A("ABCD");
    wchar_t *ptr = b ? A : L"Test OK";
    wcout << ptr << endl;

Этот код мы скомпилировали с помощью Visual Studio 2010 и он распечатал "Test OK". Может показаться, что всё работает правильно. Но внесём в код небольшую правку:

    bool b = false;
    CComBSTR A("ABCD");
    wchar_t *ptr = b ? A : L"Test OK";
    wchar_t *tmp = b ? A : L"Error!";
    wcout << ptr << endl;

Кажется строчка, где инициализируется переменная 'tmp' ничего не изменит. Но это не так. Теперь программа печатает на экран: "Error!".

Дело в том, что новый временный объект использовал ту же области памяти, что и предыдущий. Кстати, следует учитывать, что данный код по стечению обстоятельств вполне может работать. Всё зависит от везения и фазы луны. Предугадать, где будут создаваться временные объекты невозможно. Поэтому не отказывайтесь от правки кода, основываясь на утверждении "этот код правильно работал несколько лет и значит, ошибки в нём нет".

Данная диагностика классифицируется как:

CWE-416 CERT-DCL30-C

Взгляните на примеры ошибок, обнаруженных с помощью диагностики V623.