MSVC интерпретирует аргумент структуры только для перемещения как указатель
У меня есть простая структура с одним членом с удаленной копией конструкции / присваивания, и конструкция по умолчанию переместить / присваивания Я пытаюсь передать одну из этих структур в функцию по значению и вернуть член - довольно просто.
struct NoCopy {
explicit NoCopy(int x) : x{x} {}
NoCopy(const NoCopy&) = delete;
NoCopy& operator=(const NoCopy&) = delete;
NoCopy(NoCopy&&) = default;
NoCopy& operator=(NoCopy&&) = default;
int x;
};
// noinline to ensure the crash is reproducible in release
// not required to reproduce the problem code
__declspec(noinline) int problem_function(NoCopy x) {
return x.x;
}
int main() {
return problem_function(NoCopy{ 1 });
}
Проблема в том, что при компиляции с MSVC эта функция падает.
Глядя на разборку, кажется, что когда конструктор копирования удаляется, MSVC пытается интерпретировать x
как будто это было NoCopy*
и последующее чтение члена вызывает ошибку сегментации.
Вот пример Godbolt с gcc и clang для справки: https://godbolt.org/z/uIOCOX
Обратите внимание, что и gcc, и clang ведут себя как положено. Также обратите внимание, что это происходит как в оптимизированных, так и в неоптимизированных сборках, и, похоже, влияет как на MSVC 2015, так и на 2017 год.
Для справки, я компилирую на своей машине с Visual Studio Professional 2015 (14.0.25431.01 обновление 3) - и я в основном тестирую сборки x64. Мой набор инструментов платформы для аварийного воспроизведения установлен на v140.
Поэтому мой вопрос: есть ли разумные объяснения этому или я смотрю на ошибку компилятора.
редактировать: я отправил сообщение об ошибке здесь
edit #2: Если, как и я, вы застряли с похожей проблемой и не можете легко обновить VS - кажется, что определение конструктора перемещения / оператора присваивания вручную вместо использования = default
заставляет MSVC выплевывать правильный код на сайте вызовов и избегает сбоев. вот новый крестник
по этой причине такие вещи, как std::unique_ptr, похоже, не затрагиваются. Размер структуры также, кажется, является фактором.
1 ответ
Я не вижу, как это что-то кроме вопиющей ошибки компилятора. Код действителен.
Может показаться странным, что что-то столь фундаментальное уже было сломано в двух версиях MSVS, но, если бы я догадался, это будет связано с относительно новой поддержкой C++17 elision. (Конечно, я использую термин "поддержка" несколько свободно в этом случае.)
(Ошибка OP в OP здесь.)