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, вызывает ошибку при проверке использования памяти с помощью электрического ограждения.
LD_PRELOAD=libefence.so.0.0 ./a.out
Проблема заключается в том, что компилятор генерирует код, который начинает выделять новую запись на карте, а затем выполняет foo()
чтобы получить значение, чтобы положить в bar[0]
, Во время бега foo()
запись уничтожается, и код в конце концов заканчивается записью в нераспределенной памяти.
Зависит ли порядок упорядочения операций от реализации компилятора или он определен текущим стандартом C ++?
Стандарт (§1.9 15) указывает, что вычисление двух операндов для бинарного оператора не секвенировано (если только в некоторых конкретных случаях):
Если не указано иное, оценки операндов отдельных операторов
и подвыражений отдельных выражений не упорядочены.
Это означает, что он не требует, чтобы одна сторона операции присваивания была оценена перед другой, и фактически это неопределенное поведение, зависящее от порядка этих непоследовательных операций.
Это также в целом верно для порядка вычисления аргументов функции.
Вы должны разбить свое назначение на две части:
int result = foo(0);
bar[0] = result;
Других решений пока нет …