С++ STL map:: operator [], выполненный при удалении записи
std::map<int,int> bar;
int foo(int key)
{
bar.erase(key);
return 1;
}
int main()
{
bar[0] = foo(0);
return 0;
}
Этот код скомпилирован с ошибкой GCC 4.8 segs при проверке использования памяти с помощью электрического заграждения.
LD_PRELOAD=libefence.so.0.0 ./a.out
Проблема возникает из-за того, что компилятор генерирует код, который начинает выделять новую запись на карте, а затем выполняет foo()
, чтобы получить значение, помещенное в bar[0]
. При запуске foo()
запись уничтожается, и код, наконец, заканчивается записью в нераспределенной памяти.
Способ упорядочения операций зависит от реализации компилятора или задан ли он текущим стандартом С++?
Ответы
Ответ 1
В стандарте (§1.9 15) указывается, что оценка двух операндов двоичным оператором не имеет значения (если только в некоторых конкретных случаях):
За исключением тех случаев, когда отмечено, оценки операндов отдельных операторов и подвыражения отдельных выражений не подвержены.
Это означает, что он не гарантирует, что одна сторона операции присваивания оценивается перед другой, и на самом деле поведение undefined зависит от порядка этих нечеловеческих операций.
Это также справедливо для порядка оценки аргументов функции.
Вам нужно разбить свое назначение на две части:
int result = foo(0);
bar[0] = result;