Ссылка на освобожденную память является неопределенным поведением? - PullRequest
3 голосов
/ 29 мая 2020

В C ++, является ли неопределенное поведение для освобождения памяти, на которое по-прежнему ссылается ссылка, даже если эта ссылка больше не используется? Например, вызывает ли следующая функция неопределенное поведение?

void foo() {
    std::map<std::string, int> mymap;
    {
        int& val = mymap["eight"];
        val = 8;
        mymap.erase("eight"); // Oops! val still refers to mymap["eight"]
        // val is not used again
    }
    std::cout << "Entry count: " << mymap.size() << "\n";
}

Ответы [ 2 ]

0 голосов
/ 31 мая 2020

Из [associative.reqmts] p9 мы видим (выделено мной):

Члены insert и emplace не должны влиять на действительность итераторов и ссылок на контейнер, а элементы удаления должны аннулировать только итераторы и ссылки на удаленные элементы .

Это из N4659 [basi c .stc] p4 1 (снова выделено мной):

Когда достигается конец продолжительности области хранения, значения всех указателей, представляющих адрес любой части этой области хранения, становятся недействительными указателями значения (6.9.2). Косвенное обращение через недопустимое значение указателя и передача недопустимого значения указателя в функцию освобождения имеют неопределенное поведение . Любое другое использование недопустимого значения указателя имеет поведение, определяемое реализацией.

Хотя в тексте говорится конкретно об указателях, нет оснований полагать, что это не применимо к ссылкам (ну, в некотором смысле, их можно рассматривать как указатели). Также обратите внимание на тот факт, что в нем написано «Any other use», так что, пока вы не используете указатели / ссылки в выражении после того, как оно было признано недействительным, поведение должно быть четко определено.


1 Примечание: похоже, что этот текст был добавлен в N4659 и, похоже, не присутствует в более ранних версиях стандарта .

0 голосов
/ 29 мая 2020

Не определено ли поведение ссылки на освобожденную память?

Стандарт не определяет поведения для «наличия» любого значения любого типа.


mymap.erase("eight"); // Oops! val still refers to mymap["eight"]

Это то, что стандарт говорит о поведении erase:

[associative.reqmts] ... Элементы стирания становятся недействительными .. . ссылки на стертые элементы ...

Обратите внимание, что правило не говорит, что поведение не определено, если такие ссылки существуют. Фактически, было бы довольно бессмысленно описывать, что эти ссылки недействительны, если существование ссылки всегда будет подразумевать неопределенное поведение.

Что касается определения того, что такое недействительная ссылка ... стандарт, кажется, не хватает. Существует определение недопустимого указателя, но я не могу найти его для недопустимой ссылки. Такое отсутствие определения можно рассматривать как дефект в стандарте.

...