Я расследую тупиковую ошибку. Я взял ядро с gcore
и обнаружил, что одна из моих функций, похоже, вызвала себя - хотя она не делает рекурсивный вызов функции.
Вот фрагмент стека из GDB:
Thread 18 (Thread 4035926944 (LWP 23449)):
#0 0xffffe410 in __kernel_vsyscall ()
#1 0x005133de in __lll_mutex_lock_wait () from /lib/tls/libpthread.so.0
#2 0x00510017 in _L_mutex_lock_182 () from /lib/tls/libpthread.so.0
#3 0x080d653c in ?? ()
#4 0xf7c59480 in ?? () from LIBFOO.so
#5 0x081944c0 in ?? ()
#6 0x081944b0 in ?? ()
#7 0xf08f3b38 in ?? ()
#8 0xf7c3b34c in FOO::Service::releaseObject ()
from LIBFOO.so
#9 0xf7c3b34c in FOO::Service::releaseObject ()
from LIBFOO.so
#10 0xf7c36006 in FOO::RequesterImpl::releaseObject ()
from LIBFOO.so
#11 0xf7e2afbf in BAR::BAZ::unsubscribe (this=0x80d0070, sSymbol=@0xf6ded018)
at /usr/lib/gcc/x86_64-redhat-linux/3.4.6/../../../../include/c++/3.4.6/bits/stl_tree.h:176
...more stack
Я исключил некоторые имена: FOO & BAR - это пространства имен.BAZ - это класс.
Интересная часть - это # 8 и # 9, вызов Service::releaseObject()
. Эта функция не вызывает сама себя и не вызывает никаких функций, которые ее вызывают ... она не рекурсивная. Почему тогда он появляется в стеке дважды?
Это артефакт, созданный отладчиком, или он может быть реальным?
Вы заметите, что внутренний вызов ожидает мьютекса - я думаю, что это может быть моим тупиком. Service::releaseObject()
блокирует мьютекс, поэтому, если он волшебным образом телепортируется обратно внутрь себя, то наверняка может возникнуть тупик.
Некоторый фон:
Это скомпилировано с использованием g ++ v3.4.6 на RHEL4. Это 64-битная ОС, но это 32-битный код, скомпилированный с -m32. Оптимизировано при -O3. Я не могу гарантировать, что код приложения был скомпилирован с теми же параметрами, что и код LIBFOO.
Класс Service
не имеет виртуальных функций, поэтому нет vtable. Класс RequesterImpl
наследуется от полностью виртуального интерфейса, поэтому у него есть vtable.