Что может привести к сбою dynamic_cast? - PullRequest
18 голосов
/ 10 ноября 2008

У меня есть фрагмент кода, похожий на этот:

TAxis *axis = 0;
if (dynamic_cast<MonitorObjectH1C*>(obj))
   axis = (dynamic_cast<MonitorObjectH1C*>(obj))->GetXaxis();

Иногда происходит сбой:

Thread 1 (Thread -1208658240 (LWP 11400)):
#0  0x0019e7a2 in _dl_sysinfo_int80 () from /lib/ld-linux.so.2
#1  0x048c67fb in __waitpid_nocancel () from /lib/tls/libc.so.6
#2  0x04870649 in do_system () from /lib/tls/libc.so.6
#3  0x048709c1 in system () from /lib/tls/libc.so.6
#4  0x001848bd in system () from /lib/tls/libpthread.so.0
#5  0x0117a5bb in TUnixSystem::Exec () from /opt/root/lib/libCore.so.5.21
#6  0x01180045 in TUnixSystem::StackTrace () from /opt/root/lib/libCore.so.5.21
#7  0x0117cc8a in TUnixSystem::DispatchSignals ()
   from /opt/root/lib/libCore.so.5.21
#8  0x0117cd18 in SigHandler () from /opt/root/lib/libCore.so.5.21
#9  0x0117bf5d in sighandler () from /opt/root/lib/libCore.so.5.21
#10 <signal handler called>
#11 0x0533ddf4 in __dynamic_cast () from /usr/lib/libstdc++.so.6

Понятия не имею, почему он падает. obj не равно нулю (и если бы это было, это не было бы проблемой, не так ли?).

Что может быть причиной сбоя динамического приведения?

Если он не может разыграть, он должен просто вернуть NULL, нет?

Ответы [ 6 ]

37 голосов
/ 11 ноября 2008

Некоторые возможные причины аварии:

  • obj указывает на объект с неполиморфным типом (класс или структура без виртуальных методов или фундаментальный тип).
  • obj указывает на объект, который был освобожден.
  • obj указывает на не отображенную память или память, которая была отображена таким образом, чтобы при доступе генерировалось исключение (например, защитная страница или недоступная страница).
  • obj указывает на объект с полиморфным типом, но этот тип был определен во внешней библиотеке, скомпилированной с отключенным RTTI.

Не все эти проблемы обязательно вызывают сбой во всех ситуациях.

11 голосов
/ 10 ноября 2008

Я предлагаю использовать другой синтаксис для этого фрагмента кода.

if (MonitorObjectH1C* monitorObject = dynamic_cast<MonitorObjectH1C*>(obj))
{
    axis = monitorObject->GetXaxis();
}

Вы можете по-прежнему аварийно завершить работу, если какой-то другой поток удаляет то, на что указывает monitorObject, или если obj является сумасшедшим мусором, но, по крайней мере, ваша проблема больше не связана с приведением типов и вы не выполняете dynamic_cast дважды.

3 голосов
/ 10 ноября 2008

Поскольку это происходит сбой только иногда, держу пари, это проблема с многопоточностью. Проверьте все ссылки на 'obj':

grep -R 'obj.*=' .
2 голосов
/ 10 ноября 2008

Вы уверены, что значение 'obj' было правильно определено?

Если, например, они неинициализированы (то есть случайны), я могу видеть, что это вызывает сбой.

2 голосов
/ 10 ноября 2008

dynamic_cast вернет 0, если приведение завершится неудачно, и вы приведете к указателю, как в вашем случае. Проблема в том, что вы либо ранее испортили кучу кода, либо rtti не был включен.

1 голос
/ 10 ноября 2008

Может ли значение obj быть изменено другим потоком?

...