Странный сбой Qt 4.8.4 QList под Apple LLVM

Кто-нибудь знает, почему этот код падает?

Код, который вылетает:

QList<int> lst;
const auto& tmp = QList<int>() << 1;
lst = tmp;

Код, который работает (tmp не является ссылкой):

QList<int> lst;
const auto tmp = QList<int>() << 1;
lst = tmp;

Составитель:

Apple LLVM version 4.2 (clang-425.0.28) (based on LLVM 3.2svn)
Target: x86_64-apple-darwin12.5.0
Thread model: posix

Аварийное сообщение:

qt_test(76726,0x7fff76257180) malloc: *** error for object 0x101208b60: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
qt_test: line 43: 76726 Abort trap: 6           $DBG_TEST "$@"

Это сообщение появляется, когда вызывается деструктор lst.

Под VisualStudio 2012 этот код работает хорошо.

1

Решение

Подумав об этом больше, я наконец-то заметил вопиющее несоответствие.

QList<int> lst;
const auto& tmp = QList<int>() << 1;
lst = tmp;

В частности, глядя на эту строку:

const auto& tmp = QList<int>() << 1;

QList<int>() является временным. Этот временный переводится в QList<int>::operator<<(...), который затем возвращает его обратно в качестве ссылки. Проблема здесь — уровень косвенности; если вы пытались хранить QList<int>() в const-ссылку, он должен жить до тех пор, пока const-ссылка не выйдет из области видимости. Но эта ссылка была передана оператору как thisи теряется к концу утверждения.

Почему это работает в Visual Studio, а не в GCC, сомнительно. Быстрый Google для ответов появляется по крайней мере один интересный результат где он указывает на следующие пункты в стандарте:

Если выражение инициализатора является r-значением, с T2 типом класса, и «cv1 T1» совместим со ссылками с «cv2 T2», ссылка связывается одним из следующих способов (выбор определяется реализацией):

Ссылка привязана к объекту, представленному значением r, или к подобъекту с этим объектом.

Создается временный объект типа «cv1 T2», и вызывается конструктор для копирования всего объекта rvalue во временный объект. Эта ссылка связана с временным или подобъектом с временным.

Таким образом, похоже, что Visual Studio использует второй подход, который в данном случае имеет значение, поскольку значение в любом случае будет скопировано в оператор. Это действительно ставит под сомнение полезность const-ссылки, хотя.

2

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]