Возвращаемое значение из функции - PullRequest
2 голосов
/ 23 октября 2010
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. Возвращение «Hello, Unknown» из функции. Это опять-таки массив константных символов, выделенных в стеке, которые также должны быть отменены при возврате функции. Тем не менее, это не так, и я предполагаю, что это из-за оптимизации возвращаемого значения.

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

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

Ответы [ 2 ]

11 голосов
/ 23 октября 2010

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

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

1 голос
/ 23 октября 2010

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

...