Способствует ли string_view ошибкам использования после освобождения? - PullRequest
3 голосов
/ 22 апреля 2019

Согласно статье ( здесь и там ) этот код является ошибочным примером использования без использования:

#include <iostream>
#include <string>
#include <string_view>

int main() {
  std::string s = "Hellooooooooooooooo ";
  std::string_view sv = s + "World\n";
  std::cout << sv;
}

В статье указаночто string s будут освобождены при использовании string_view!Это противоречит моему опыту отладки.Но я прошу вас подтвердить / проверить / проверить это.

По моему опыту, переменные стека / области видимости освобождаются (вызов деструктора был бы гораздо более правильной формулировкой) при выходе из области видимости.Это означает, что в этом случае это произойдет ПОСЛЕ std::cout << sv;

Однако я никогда не использовал string_view, поэтому я не знаю никакой внутренней механики этого объекта.

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


РЕДАКТИРОВАТЬ : после первых двух ответов это действительно использование после освобождения.

Вспомогательный вопрос: как вы думаете, мы могли бы добавить конструктор перемещения с ключевым словом delete в определении string_view, чтобы запретить это?

Ответы [ 2 ]

3 голосов
/ 22 апреля 2019

Выражение s + “World\n” приводит к временному объекту.Время жизни этого временного std::string достаточно велико для инициализации sv.Память, на которую ссылается sv, освобождается сразу после инициализации (когда уничтожается временный объект).

3 голосов
/ 22 апреля 2019

Проблема с этим кодом ...

std::string_view sv = s + "World\n";

... заключается в том, что sv не установлен на s, а на безымянный временный , созданный выражениемs + "world\n".Это временное уничтожается сразу после окончания всего выражения (в точке с запятой).

Так что да, это ошибка типа «использовать после освобождения».

Если выЕсли вы хотите продлить срок жизни этого временного , вам нужно присвоить его переменной, которая будет его поддерживать - например, новый объект std::string:

std::string sv = s + "World\n"; // copy the temporary to new storage in sv

A std::string_view - это просто«просмотр» на строку, это не строка сама по себе.Он действителен только в том случае, если строка, на которую он «смотрит», действительна.

Здесь есть еще одна странность.Вы также можете привязать временный к const справочнику , который продлевает срок службы временных:

std::string const& sv = s + "World\n"; // just keep the temporary living

Почему инициализация std::string_view из временно разрешено?

Я не могу говорить за комитет по стандартам, но я подозреваю, что std::string_view предполагается использовать в качестве параметра функции, чтобы временные функции могли быть переданы в функцию (как с const ref).Очевидно, что жизненный путь подходит для этого сценария.

Если мы запретим инициализацию для временных пользователей, то основное использование std::string_view будет отменено.Вы будете вынуждены создать новый std::string (или привязку к const ref) перед вызовом функции, что сделает процесс неудобным.

...