Возврат значения из функции

const char *Greet(const char *c) {
    string name;
    if(c)
        name = c;
    if (name.empty())
        return "Hello, Unknown";
    return name.c_str();
}

int _tmain(int argc, _TCHAR* argv[])
{
    cout << Greet(0) << '\t' << Greet("Hello, World") << endl;
    return 0;
}

Я вижу 2 ошибки с приведенным выше кодом.

  1. Возврат c_str из строкового объекта, определенного локально для функции. Строка уничтожается, когда функция возвращается, и ясно, что c_str() будет указывать на часть памяти, которая освобождена.

  2. Возврат «Привет, Неизвестный» из функции. Это снова массив константных символов, выделенных в стеке, который также должен быть освобожден, когда функция возвращается. Однако это не так, и я предполагаю, что это связано с оптимизацией возвращаемого значения.

Верно ли мое понимание выше?

PS: я протестировал приведенный выше код как с gcc, так и с MSVC10. GCC отлично выполняет приведенный выше код и не генерирует никаких ошибок времени выполнения или неопределенного поведения как для строкового объекта, так и для постоянной строки. MSVC10 отображает мусорные данные для строкового объекта, но правильно печатает постоянную строку.


person naivnomore    schedule 22.10.2010    source источник
comment
Ну, технически поведение GCC для Greet("Hello, World") не не определено.   -  person AlcubierreDrive    schedule 23.10.2010


Ответы (2)


Номер 1 правильный. Указатель, возвращенный из c_str(), становится недействительным, когда name уничтожается. Разыменование указателя после name приводит к неопределенному поведению. В ваших тестах под gcc он похоже работает; под Visual C++ он печатает мусор. Возможны любые результаты, когда поведение не определено.

Номер 2 неверный. "Hello, Unknown" — строковый литерал. Строковые литералы имеют статическую продолжительность хранения (они существуют с момента запуска программы до ее завершения. Вы возвращаете указатель на этот строковый литерал, и этот указатель действителен даже после возврата функции.

person James McNellis    schedule 22.10.2010

Строковые литералы имеют статическое хранилище, поэтому не освобождаются в конце функции.

person Oliver Charlesworth    schedule 22.10.2010