Seg Fault при использовании QSharedPointers в qt5

Я использую qt5.5.1 с qt-creator 3.5.1 и пытаюсь установить стиль для GeoDataPlacemark с помощью GeoDataStyle. Раньше это работало нормально, но после обновления Marble для использования общих указателей вместо прямых указателей в моей программе произошел сбой сегментации. Используя GDB, я проследил ошибку seg до строки, где я создаю QSharedPointer с прямым указателем styleArch. Кто-нибудь знает, в чем может быть проблема?

Мой старый код был следующим:

styleArch->setIconStyle( *icon );
place->setStyle( styleArch ); //Old Marble

Новый код, использующий новый Marble API, выглядит следующим образом:

styleArch->setIconStyle( *icon );
place->setStyle(Marble::GeoDataStyle::Ptr( styleArch )); //New Marble

Спасибо за ваше время!


person Eric Horng    schedule 13.02.2017    source источник


Ответы (1)


Строка: Marble::GeoDataStyle::Ptr( styleArch ) создает временный QSharedPointer и передает ему styleArch в качестве указателя. В этот момент QSharedPointer становится владельцем styleArch*, а это означает, что любой ранее принадлежавший styleArch* больше не имеет его.

Метод setStyle принимает константная ссылка на временный QSharedPointer, который вы только что создали, и использует его кратко, но, что важно, не увеличивает счетчик ссылок QSharedPointer (поскольку он является константным).

Это означает, что как только вызов setStyle завершается, временный QSharedPointer выходит из области видимости (вызывает свой деструктор) и удаляет объект styleArch из кучи. Это оставляет вас в плохом положении, потому что первоначальный владелец styleArch* понятия не имеет, что теперь он содержит недопустимый указатель. Любое дальнейшее использование styleArch* должно привести к ошибке сегментации.

Самым простым решением было бы обновить владельца styleArch*, чтобы вместо этого удерживать QSharedPointer‹> для стилевой арки.

person James Fegan    schedule 13.02.2017
comment
Привет, спасибо за ваш быстрый ответ! Ваш комментарий указал мне правильное направление. Я создал новую переменную типа QSharedPointer‹GeoDataStyle› вот так: styleArchSP = QSharedPointer<GeoDataStyle>(new GeoDataStyle); styleArchSP->setIconStyle( *icon ); place->setStyle( styleArchSP ); - person Eric Horng; 17.02.2017
comment
В яблочко. Создавая экземпляр общего указателя как styleArchSP, вы гарантируете, что его время жизни выходит за рамки вызова setStyle. Это решило вашу проблему с ошибкой сегмента? - person James Fegan; 17.02.2017
comment
Да, это так. Большое спасибо! - person Eric Horng; 18.02.2017