Временный объект освобождается по стандарту, что приводит к неопределенному поведению . Реализация может делать все что угодно, в том числе хранить байты объекта в стековой памяти до тех пор, пока они не будут перезаписаны, что позволяет вашему коду (некорректно) работать.
Когда я разобрал двоичный файл, созданный моим компилятором (clang ++ 9.0.1) Я заметил, что указатель стека не «регрессировал», когда блок, содержащий data
, закончился, таким образом предотвращая его перезапись, когда cout << "main loop" << endl;
приводил к вызовам функций.
Кроме того, из-за короткой строки При оптимизации фактический ASCII "123" хранится в самом объекте std::string
, а не в буфере, выделенном для кучи.
Проект чернового стандарта гласит следующее:
6.6.4.3 Автоматическое c срок хранения
Переменные области действия блока, явно не объявленные как stati c, thread_local или extern, имеют автоматическое c хранилище продолжительность. Хранение этих сущностей длится до тех пор, пока блок, в котором они созданы, не выйдет из системы .
Экспериментально, если я сделаю строку достаточно длинной, чтобы отключить оптимизацию короткой строки, программа все еще молча работает, поскольку байты в буфере остаются неизменными в моем эксперименте . Если я включаю ASAN, я получаю правильное предупреждение об использовании кучи после освобождения, потому что байты были освобождены в конце времени жизни строки, но к ним обращались через недопустимое использование указателя на теперь разрушенную строку.