Камрады, ай нид хелп. Не могу понять в чом дело. У меня тут есть логгер, который крашится в рантайме но в дебаге но полезного нет почти.
При запущенной валгринд с мемчеком — не крашится.
Принцип такой: при добавлении строки оно открывает ofstream в файл, пишет туда строку, закрывает.
Крашится как раз на открытии ofstream
Я предполагал что это краш в другом потоке, но уже дважды всё там переписал — не должно
Ну и крашится на вызове логгера из деструктора объекта. При этом оно к объекту самому разрушаемому не обращается
сам логгер — синглтон, создаётся при первом обращении, удаляется при выходе из приложения
Полный стек вызовов, крашится в Thread 1:
Thread 7 (Thread 0x7fffc68e1700 (LWP 31402)):
#0 0x00007ffff595b6c6 in ppoll () from /lib64/libc.so.6
No symbol table info available.
#1 0x00007ffff36ab901 in pa_mainloop_poll () from /usr/lib64/libpulse.so.0
No symbol table info available.
#2 0x00007ffff36abf10 in pa_mainloop_iterate () from /usr/lib64/libpulse.so.0
No symbol table info available.
#3 0x00007ffff780c2a7 in PULSEAUDIO_WaitDevice () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#4 0x00007ffff779442e in SDL_RunAudio () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#5 0x00007ffff779375c in SDL_RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#6 0x00007ffff7809ac9 in RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#7 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
No symbol table info available.
#8 0x00007ffff59671af in clone () from /lib64/libc.so.6
No symbol table info available.
Thread 6 (Thread 0x7fffd72e2700 (LWP 31401)):
#0 0x00007ffff5c3d30c in __lll_lock_wait () from /lib64/libpthread.so.0
No symbol table info available.
#1 0x00007ffff5c357a2 in pthread_mutex_lock () from /lib64/libpthread.so.0
No symbol table info available.
#2 0x00007ffff73401cf in Urho3D::WorkQueue::ProcessItems(unsigned int) () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#3 0x00007ffff7339f1a in Urho3D::ThreadFunctionStatic(void*) () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#4 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
No symbol table info available.
#5 0x00007ffff59671af in clone () from /lib64/libc.so.6
No symbol table info available.
Thread 5 (Thread 0x7fffd7ae3700 (LWP 31400)):
#0 0x00007ffff5c3d30c in __lll_lock_wait () from /lib64/libpthread.so.0
No symbol table info available.
#1 0x00007ffff5c357a2 in pthread_mutex_lock () from /lib64/libpthread.so.0
No symbol table info available.
#2 0x00007ffff73401cf in Urho3D::WorkQueue::ProcessItems(unsigned int) () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#3 0x00007ffff7339f1a in Urho3D::ThreadFunctionStatic(void*) () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#4 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
No symbol table info available.
#5 0x00007ffff59671af in clone () from /lib64/libc.so.6
No symbol table info available.
Thread 4 (Thread 0x7fffd82e4700 (LWP 31399)):
#0 0x00007ffff5c3d30c in __lll_lock_wait () from /lib64/libpthread.so.0
No symbol table info available.
#1 0x00007ffff5c357a2 in pthread_mutex_lock () from /lib64/libpthread.so.0
No symbol table info available.
#2 0x00007ffff73401cf in Urho3D::WorkQueue::ProcessItems(unsigned int) () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#3 0x00007ffff7339f1a in Urho3D::ThreadFunctionStatic(void*) () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#4 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
No symbol table info available.
#5 0x00007ffff59671af in clone () from /lib64/libc.so.6
No symbol table info available.
Thread 3 (Thread 0x7fffdbfff700 (LWP 31398)):
#0 0x00007ffff5c3e138 in nanosleep () from /lib64/libpthread.so.0
No symbol table info available.
#1 0x00000000004b0f90 in std::this_thread::sleep_for<long, std::ratio<1l, 1000l> > (__rtime=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:376
__s = {__r = 0}
__ns = {__r = 100000000}
__ts = {tv_sec = 0, tv_nsec = 36163799}
#2 0x00000000004b06b5 in eing::world::CWorld::worldThread (this=0x7b4640) at ../../../src/world/cworld.cpp:89
No locals.
#3 0x00000000004b2e41 in std::__invoke_impl<void, void (eing::world::CWorld::*)(), eing::world::CWorld*> (__f=@0x839ac0: (void (eing::world::CWorld::*)(eing::world::CWorld * const)) 0x4b0660 <eing::world::CWorld::worldThread()>, __t=@0x839ab8: 0x7b4640) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/invoke.h:73
No locals.
#4 0x00000000004b2d52 in std::__invoke<void (eing::world::CWorld::*)(), eing::world::CWorld*> (__fn=@0x839ac0: (void (eing::world::CWorld::*)(eing::world::CWorld * const)) 0x4b0660 <eing::world::CWorld::worldThread()>, __args=@0x839ab8: 0x7b4640) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/invoke.h:95
No locals.
#5 0x00000000004b2d12 in std::thread::_Invoker<std::tuple<void (eing::world::CWorld::*)(), eing::world::CWorld*> >::_M_invoke<0ul, 1ul> (this=0x839ab8) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:234
No locals.
#6 0x00000000004b2cc5 in std::thread::_Invoker<std::tuple<void (eing::world::CWorld::*)(), eing::world::CWorld*> >::operator() (this=0x839ab8) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:243
No locals.
#7 0x00000000004b2a99 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (eing::world::CWorld::*)(), eing::world::CWorld*> > >::_M_run (this=0x839ab0) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:186
No locals.
#8 0x00007ffff6142f0e in std::execute_native_thread_routine (__p=0x839ab0) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/src/c++11/thread.cc:83
__t = {_M_t = {_M_t = {<std::_Tuple_impl<0, std::thread::_State*, std::default_delete<std::thread::_State> >> = {<std::_Tuple_impl<1, std::default_delete<std::thread::_State> >> = {<std::_Head_base<1, std::default_delete<std::thread::_State>, true>> = {<std::default_delete<std::thread::_State>> = {<No data fields>}, <No data fields>}, <No data fields>}, <std::_Head_base<0, std::thread::_State*, false>> = {_M_head_impl = 0x839ab0}, <No data fields>}, <No data fields>}}}
#9 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
No symbol table info available.
#10 0x00007ffff59671af in clone () from /lib64/libc.so.6
No symbol table info available.
Thread 2 (Thread 0x7ffff7fed700 (LWP 31397)):
#0 0x00007ffff595b6c6 in ppoll () from /lib64/libc.so.6
No symbol table info available.
#1 0x00007ffff36ab901 in pa_mainloop_poll () from /usr/lib64/libpulse.so.0
No symbol table info available.
#2 0x00007ffff36abf10 in pa_mainloop_iterate () from /usr/lib64/libpulse.so.0
No symbol table info available.
#3 0x00007ffff36abfa0 in pa_mainloop_run () from /usr/lib64/libpulse.so.0
No symbol table info available.
#4 0x00007ffff780c40f in HotplugThread () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#5 0x00007ffff779375c in SDL_RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#6 0x00007ffff7809ac9 in RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#7 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
No symbol table info available.
#8 0x00007ffff59671af in clone () from /lib64/libc.so.6
No symbol table info available.
Thread 1 (Thread 0x7ffff7f830c0 (LWP 31391)):
#0 0x00007ffff589976b in raise () from /lib64/libc.so.6
No symbol table info available.
#1 0x00007ffff589afb1 in abort () from /lib64/libc.so.6
No symbol table info available.
#2 0x00007ffff58e02e7 in __libc_message () from /lib64/libc.so.6
No symbol table info available.
#3 0x00007ffff58e8038 in malloc_printerr () from /lib64/libc.so.6
No symbol table info available.
#4 0x00007ffff58e83be in malloc_consolidate () from /lib64/libc.so.6
No symbol table info available.
#5 0x00007ffff58eb1d8 in _int_malloc () from /lib64/libc.so.6
No symbol table info available.
#6 0x00007ffff58eceaa in malloc () from /lib64/libc.so.6
No symbol table info available.
#7 0x00007ffff6116418 in operator new (sz=8192) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/libsupc++/new_op.cc:50
p = <optimized out>
#8 0x00007ffff61164c5 in operator new[] (sz=<optimized out>) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/libsupc++/new_opv.cc:32
No locals.
#9 0x00007ffff617b6f8 in std::basic_filebuf<char, std::char_traits<char> >::_M_allocate_internal_buffer (this=0x794ec8) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:55
this = 0x794ec8
#10 0x00007ffff617fd12 in std::basic_filebuf<char, std::char_traits<char> >::open (this=0x794ec8, __s=0x795800 "logs/cube_helper/2018-12-16_18-12-02.application.log", __mode=19) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:187
__ret = 0x0
__s = 0x795800 "logs/cube_helper/2018-12-16_18-12-02.application.log"
__mode = 19
this = 0x794ec8
__ret = <optimized out>
__ret = 0x0
#11 0x00007ffff617fe43 in std::basic_filebuf<char, std::char_traits<char> >::open (__mode=<optimized out>, __s=..., this=0x794ec8) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/fstream:308
No locals.
#12 std::basic_ofstream<char, std::char_traits<char> >::open (this=0x794ec0, __s=..., __mode=<optimized out>) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/fstream:823
No locals.
#13 0x00000000004aef98 in eing::tools::logger::CLogger::start (this=0x794e80) at ../../../src/tools/logger/clogger.cpp:63
time = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7958d0 "P\223\330\367\377\177"}, _M_string_length = 7949920, {_M_local_buf = "\320\\y\000\000\000\000\000\200\006\365\000\000\000\000", _M_allocated_capacity = 7953616}}
#14 0x00000000004cc16d in eing::graphic::world::CDynamicMesh::~CDynamicMesh (this=0x1073aa0) at ../../../src/graphic/world/cdynamicmesh.cpp:40
No locals.
#15 0x000000000049692e in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:48
No locals.
#16 0x0000000000496c89 in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:41
No locals.
#17 0x000000000045c05f in eing_helper::cube::AppCubeHelper::redrawTestCube (this=0x77cee0) at ../../../src/applications/cube_helper/main.cpp:350
e = @0xae6100: {_vptr.exception = 0xae61b0}
#18 0x000000000045d2af in eing_helper::cube::AppCubeHelper::HandleUpdate (this=0x77cee0, eventType=..., eventData=...) at ../../../src/applications/cube_helper/main.cpp:289
yaw_ = 0
pitch_ = 0
timeStep = 0.00499999989
MOVE_SPEED = 10
MOUSE_SENSITIVITY = 0.100000001
#19 0x0000000000460bc7 in Urho3D::EventHandlerImpl<eing_helper::cube::AppCubeHelper>::Invoke (this=0x106aff0, eventData=...) at /usr/include/Urho3D/Physics/../Core/Object.h:315
receiver = 0x77cee0
#20 0x00007ffff732d642 in Urho3D::Object::OnEvent(Urho3D::Object*, Urho3D::StringHash, Urho3D::HashMap<Urho3D::StringHash, Urho3D::Variant>&) () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#21 0x00007ffff732e93f in Urho3D::Object::SendEvent(Urho3D::StringHash, Urho3D::HashMap<Urho3D::StringHash, Urho3D::Variant>&) () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#22 0x00007ffff734d1d7 in Urho3D::Engine::Update() () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#23 0x00007ffff735013a in Urho3D::Engine::RunFrame() () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#24 0x00007ffff7342e45 in Urho3D::Application::Run() () from /usr/lib/Urho3D/libUrho3D.so.0
No symbol table info available.
#25 0x000000000045d44a in main (argc=1, argv=0x7fffffffe018) at ../../../src/applications/cube_helper/main.cpp:378
graphic_result = 0
Накидайте идей что это может быть? Может уже встречалось такое?...
Здравствуйте, Sheridan, Вы писали:
S>Через раз показывает причину: S>
S>malloc_consolidate(): invalid chunk size
S>
S>Полный стек вызовов, крашится в Thread 1: S>
Thread 1 (Thread 0x7ffff7f830c0 (LWP 31391)):
#0 0x00007ffff589976b in raise () from /lib64/libc.so.6
No symbol table info available.
#1 0x00007ffff589afb1 in abort () from /lib64/libc.so.6
No symbol table info available.
#2 0x00007ffff58e02e7 in __libc_message () from /lib64/libc.so.6
No symbol table info available.
#3 0x00007ffff58e8038 in malloc_printerr () from /lib64/libc.so.6
No symbol table info available.
#4 0x00007ffff58e83be in malloc_consolidate () from /lib64/libc.so.6
No symbol table info available.
#5 0x00007ffff58eb1d8 in _int_malloc () from /lib64/libc.so.6
No symbol table info available.
#6 0x00007ffff58eceaa in malloc () from /lib64/libc.so.6
No symbol table info available.
#7 0x00007ffff6116418 in operator new (sz=8192) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/libsupc++/new_op.cc:50
p = <optimized out>
#8 0x00007ffff61164c5 in operator new[] (sz=<optimized out>) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/libsupc++/new_opv.cc:32
No locals.
#9 0x00007ffff617b6f8 in std::basic_filebuf<char, std::char_traits<char> >::_M_allocate_internal_buffer (this=0x794ec8) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:55
this = 0x794ec8S>
S>Накидайте идей что это может быть? Может уже встречалось такое?...
Скорее всего, где-то проехал по памяти. Или записал в невыделенный/освобожденный участок, или два раза удалил один объект.
У сложных вещей обычно есть и хорошие, и плохие аспекты.
Берегите Родину, мать вашу. (ДДТ)
Здравствуйте, reversecode, Вы писали:
R>valgrind для слабаков, давайте будем угадывать R>любой мемори трейсер даст ответ что вы там с памятью накрутили
... S>Накидайте идей что это может быть? Может уже встречалось такое?...
попробуй заменить строку m_filename на m_filename.c_str() или на std::string(m_filename)
Здравствуйте, kov_serg, Вы писали:
S>>Накидайте идей что это может быть? Может уже встречалось такое?... _>попробуй заменить строку m_filename на m_filename.c_str() или на std::string(m_filename)
Пробовал, не помогает. По разному пробовал.
Здравствуйте, Sheridan, Вы писали:
S>Ну и крашится на вызове логгера из деструктора объекта. При этом оно к объекту самому разрушаемому не обращается S>сам логгер — синглтон, создаётся при первом обращении, удаляется при выходе из приложения
А этот объект, в деструкторе которого все происходит, сам часом не является объектом со статическим временем жизни, живущим дольше логгера, по закону подлости? Общей константой, например, или просто глобальным объектом? Может, находится во владении какого-то другого статика?
Здравствуйте, Sheridan, Вы писали:
S>сам логгер — синглтон, создаётся при первом обращении, удаляется при выходе из приложения
S>Накидайте идей что это может быть? Может уже встречалось такое?...
А объект логгера на момент крэша ещё жив?
Вообще, идея делать логгер синглетоном, создающимся по требованию, делает плохо контролируемым момент его разрушения.
При этом то, что логгеру нужно, инициализироваться по требованию, наводит на мысль, что его зовут из конструкторов статических объектов...
За одно и из деструкторов его не могут звать, часом?
Кстати, а зачем его вообще разрушают?
Можно попробовать или сделать логгер глобальным статическим объектом, задав ему высокий приоритет инициализации.
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, rg45, Вы писали:
R>А этот объект, в деструкторе которого все происходит, сам часом не является объектом со статическим временем жизни, живущим дольше логгера, по закону подлости? Общей константой, например, или просто глобальным объектом? Может, находится во владении какого-то другого статика?
Нет. )
Здравствуйте, Erop, Вы писали:
S>>сам логгер — синглтон, создаётся при первом обращении, удаляется при выходе из приложения S>>Накидайте идей что это может быть? Может уже встречалось такое?...
E>А объект логгера на момент крэша ещё жив?
Да.
E>Вообще, идея делать логгер синглетоном, создающимся по требованию, делает плохо контролируемым момент его разрушения.
Он не разрушается. Точнее разрушается когда сам синглтон разрушается. Всмысле есть один большой синглтон, который в себе хранит указатели на объекты, которые должны быть в единственном экземпляре. Создаёт эти объекты при первом запросе и удаляет в своём деструкторе.
E>При этом то, что логгеру нужно, инициализироваться по требованию, наводит на мысль, что его зовут из конструкторов статических объектов... E>За одно и из деструкторов его не могут звать, часом?
Нет, первый вызов из main() вообще.
E>Кстати, а зачем его вообще разрушают?
Его не разрушают, точнее разрушают при дестрое снглтона, который дестроится при выходе из приложения. ))
E>Можно попробовать или сделать логгер глобальным статическим объектом, задав ему высокий приоритет инициализации.
Ну, собственно, так сейчас и есть. И до креша логгер успевает много чего понаписать.
Здравствуйте, Sheridan, Вы писали:
E>>За одно и из деструкторов его не могут звать, часом? S>Нет, первый вызов из main() вообще.
А зачем тогда вся химия с синглетонами? Почему не просто статический объект?
E>>Кстати, а зачем его вообще разрушают? S>Его не разрушают, точнее разрушают при дестрое снглтона, который дестроится при выходе из приложения. ))
Выход из приложение -- это очень долго. В частности это вызов деструкторов всех статических объектов...
S>Ну, собственно, так сейчас и есть. И до креша логгер успевает много чего понаписать.
Так значит крэш таки на этапе деструкторов статических объектов? Или в main()?
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Здравствуйте, Sheridan, Вы писали:
S>Камрады, ай нид хелп. Не могу понять в чом дело. У меня тут есть логгер, который крашится в рантайме но в дебаге но полезного нет почти. S>При запущенной валгринд с мемчеком — не крашится.
Теперь тебе понятно, почему люди сделали Java и C#, и стали писать на них?
Здравствуйте, Erop, Вы писали:
E>>>За одно и из деструкторов его не могут звать, часом? S>>Нет, первый вызов из main() вообще. E>А зачем тогда вся химия с синглетонами? Почему не просто статический объект?
Неважно. По факту есть всего один синглтон, который один раз создаётся, один раз удаляется за время жизни приложения. Неважно как.
E>>>Кстати, а зачем его вообще разрушают? S>>Его не разрушают, точнее разрушают при дестрое снглтона, который дестроится при выходе из приложения. )) E>Выход из приложение -- это очень долго. В частности это вызов деструкторов всех статических объектов...
Ы том то и дело что крешится не тогда когда выход из приложения.
S>>Ну, собственно, так сейчас и есть. И до креша логгер успевает много чего понаписать. E>Так значит крэш таки на этапе деструкторов статических объектов? Или в main()?
Не статических. Я создаю и удаляю объект.... Крч.
Здравствуйте, Слава, Вы писали:
С>Теперь тебе понятно, почему люди сделали Java и C#, и стали писать на них?
Потому что не осилили разобраться с достаточно простой проблемой? Заплакали, бросили но полпути и к жабе за решотку?
С>PS: переходи на Rust.
Надо будет — и на ём буду писать. Но шас не хочу.
Здравствуйте, rg45, Вы писали:
R>Упс. А утебя реально new и delete вот так по коду исппользуются, не смар-поинтеры? Так может, ты просто где-нидудь дважды удаляешь какой-то объект?
Использование смартпоинтеров считаю признаком плохого тона и отсутствию понимания о времени жизни объектов и проекта вообще. Мол, "мы сами неместные, хрен вас знает что где у всё тут нужно и когда. Поэтому вот есть смартпоинтер, он сам поймет когда удалицца". Но это тема для срача в КСВ, если есть желание — надо дуть туда.
Я же точно знаю время жизни своих объектов.
Дважды — точно нет. Если конечно std::list в remove не вызывает за каким то хреном delete для хранящихся в ём указателей...
Здравствуйте, sgenie, Вы писали:
S>А где в CSingleTone логгер инициализируется в NULL?
В двух местах. Второе — лишнее, но макросу пофигу. В nullptr. При создании CSingleTone и при уничтожении.
Здравствуйте, Sheridan, Вы писали:
S>Использование смартпоинтеров считаю признаком плохого тона и отсутствию понимания о времени жизни объектов и проекта вообще. Мол, "мы сами неместные, хрен вас знает что где у всё тут нужно и когда. Поэтому вот есть смартпоинтер, он сам поймет когда удалицца". Но это тема для срача в КСВ, если есть желание — надо дуть туда. S>Я же точно знаю время жизни своих объектов. S>Дважды — точно нет. Если конечно std::list в remove не вызывает за каким то хреном delete для хранящихся в ём указателей...
Ну, это ты зря. Смартпоинтеры и вообще RAII — это не только и не столько контроль времени жизни, это еще и безопасность с точки зрения исключений, и общее качество структуры кода. Этот устав написан кровью:
Здравствуйте, Sheridan, Вы писали:
S> Использование смартпоинтеров считаю признаком плохого тона и отсутствию понимания о времени жизни объектов и проекта вообще. Мол, "мы сами неместные, хрен вас знает что где у всё тут нужно и когда. Поэтому вот есть смартпоинтер, он сам поймет когда удалицца". Но это тема для срача в КСВ, если есть желание — надо дуть туда. S> Я же точно знаю время жизни своих объектов.
Смелое заявление.
S> Проблемы есть, но не в моём коде.
Очень смелое заявление .
S> А где в CSingleTone логгер инициализируется в NULL? S> В двух местах. Второе — лишнее, но макросу пофигу. В nullptr. При создании CSingleTone и при уничтожении.
Здравствуйте, Sheridan, Вы писали:
S>Накидайте идей что это может быть? Может уже встречалось такое?...
Судя по описанию, причина падения почти наверняка с порядком создания/разрушения глобальных (включая статик) объектов. Например, если где-то используется std::cout/std::cerr/std::cin, то вполне возможно, что их попытались использовать до создания или после разрушения.
Так же падение возможно, если главный поток (нить) не дожидается завершения других нитей.
Здравствуйте, Hobbes, Вы писали:
_>>попробуй заменить строку m_filename на m_filename.c_str() или на std::string(m_filename) H>Чем это может помочь?
Это могло сразу падать в случае проблем с this или this->m_filename
Здравствуйте, Sheridan, Вы писали:
S>Полный стек вызовов, крашится в Thread 1:
...
#15 0x000000000049692e in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:48
#16 0x0000000000496c89 in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:41
...
S>Накидайте идей что это может быть? Может уже встречалось такое?...
А что твориться в файле cblock.cpp в строках 40-50
Предположу по собственным граблям, что проблема не в недрах std, а в коррупте памяти еще до вызова.
Возможные причины: необнуление указателей в членах класса в конструкторе с последующим удалением.
Пронос мимо памяти по индексу в массиве с последующей попыткой удаления объекта
Удаление одного и того же объекта дважды
кривой #pragma pack
ну и попытка конкурентной записи в лог при отсутствии лока на стрим-это харакири
по симптомам лидирует первый вариант, за него работоспособность в отладочном виде и под всякими valgrid'ами, они любят отдавать в new обнуленную память вместо мусора
Здравствуйте, Sheridan, Вы писали:
S>Здравствуйте, sgenie, Вы писали:
S>>А где в CSingleTone логгер инициализируется в NULL? S>В двух местах. Второе — лишнее, но макросу пофигу. В nullptr. При создании CSingleTone и при уничтожении.
При каких условиях освобождается память под m_logger и является ли освобождение памяти потокобезопасным? Может ли в твоём коде происходить:
1. поток 1 освободил память m_logger
2. поток 2 попытался что-то записать в лог
3. поток 1 обнулил m_logger.
Здравствуйте, Sheridan, Вы писали:
S>Накидайте идей что это может быть? Может уже встречалось такое?...
Конечно, в 99% проблема коде которая используюет библиотеку. Посмотри внимательно на свой код, выделение/удаление ресурсов и удели внимание многопоточному взаимодействию.
Здравствуйте, Слава, Вы писали:
С>Теперь тебе понятно, почему люди сделали Java и C#, и стали писать на них?
Только проблемы в джава и C# не были решены, а были перенесены в другую плоскость. С>PS: переходи на Rust.
А вот тут попытались решить, кстати.
Здравствуйте, ViTech, Вы писали:
S>> А где в CSingleTone логгер инициализируется в NULL? S>> В двух местах. Второе — лишнее, но макросу пофигу. В nullptr. При создании CSingleTone и при уничтожении.
VT>Хорошо бы показать код инициализации.
Ничего там сверхестественного...
Здравствуйте, AleksandrN, Вы писали:
AN>При каких условиях освобождается память под m_logger и является ли освобождение памяти потокобезопасным? Может ли в твоём коде происходить: AN>1. поток 1 освободил память m_logger AN>2. поток 2 попытался что-то записать в лог AN>3. поток 1 обнулил m_logger.
Нет. Логгер создаётся при старте приложения и удаляется при выходе. Пока приложение работает — логгер априори жив.
BFE>Метод logger() не является потокобезопасным. Если он вызывается из двух и более ниток, то может быть создано два и более объектов типа CLogger.
Знаю. Там где крашится — поток из которгго пишутся логи — единственный.
Здравствуйте, kov_serg, Вы писали:
_>Здравствуйте, Sheridan, Вы писали:
S>>Полный стек вызовов, крашится в Thread 1: _>
_>...
_>#15 0x000000000049692e in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:48
_>#16 0x0000000000496c89 in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:41
_>...
_>
S>Накидайте идей что это может быть? Может уже встречалось такое?... _>А что твориться в файле cblock.cpp в строках 40-50
Это деструктор.
Здравствуйте, Sheridan, Вы писали:
S>>>Полный стек вызовов, крашится в Thread 1: _>>
_>>...
_>>#15 0x000000000049692e in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:48
_>>#16 0x0000000000496c89 in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:41
_>>...
_>>
S>Накидайте идей что это может быть? Может уже встречалось такое?... _>>А что твориться в файле cblock.cpp в строках 40-50 S>Это деструктор.
Здравствуйте, Sheridan, Вы писали:
S>Здравствуйте, kov_serg, Вы писали:
_>>Здравствуйте, Sheridan, Вы писали:
S>>>Полный стек вызовов, крашится в Thread 1: _>>
_>>...
_>>#15 0x000000000049692e in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:48
_>>#16 0x0000000000496c89 in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:41
_>>...
_>>
S>Накидайте идей что это может быть? Может уже встречалось такое?... _>>А что твориться в файле cblock.cpp в строках 40-50 S>Это деструктор. S>
Смущает что в #15 и #16 this одинаковый (0x105d070) т.е. сначала 48: delete m_dynamicMesh; а затем контрольный #41 ~CBlock() -- очень подозрительно, или нумерация строк съехала.
я бы добавил что-то вида
struct CBlock {
...
struct State { int x; State() { x=0; } ~State() { if (x) panic(); x=1; } } state;
...
~CBlock() {
if (state.x) panic();
...
Здравствуйте, Sheridan, Вы писали:
S>Я предполагал что это краш в другом потоке, но уже дважды всё там переписал — не должно S>Ну и крашится на вызове логгера из деструктора объекта. При этом оно к объекту самому разрушаемому не обращается
Ещё вариант: у базового объекта нет виртуального деструктора, а у наследника деструктор виртуальный.
Здравствуйте, kov_serg, Вы писали:
_>Смущает что в #15 и #16 this одинаковый (0x105d070) т.е. сначала 48: delete m_dynamicMesh; а затем контрольный #41 ~CBlock() -- очень подозрительно, или нумерация строк съехала.
Да, меня тоже это смущает, но я склоняюсь к мысли что дебаггер тут просто показывает место вызова delete в деструкторе.
I>Добавь проверку что m_logstream.open был успешен.
Проходил через это. Даже вообще по месту новый создавал явно. Не помогает. Всё больше склоняюсь к мысли что не в логгере дело.
Здравствуйте, B0FEE664, Вы писали:
BFE>Ещё вариант: у базового объекта нет виртуального деструктора, а у наследника деструктор виртуальный.
Есть виртуальный, есть...
Здравствуйте, nekocoder, Вы писали:
S>>Я же точно знаю время жизни своих объектов. N>Нет, не знаешь. Поэтому у тебя портится память и ты мучаешься с непонятным крашем.
У меня не портится. А вот за urho3d не ручаюсь. Достаточно посмотреть на реализацию их "умных" указателей, не к ночи они помянуты будут...
Здравствуйте, Sheridan, Вы писали:
S>#17 0x000000000045c05f in eing_helper::cube::AppCubeHelper::redrawTestCube (this=0x77cee0) at ../../../src/applications/cube_helper/main.cpp:350 S> e = @0xae6100: {_vptr.exception = 0xae61b0} S>#18 0x000000000045d2af in eing_helper::cube::AppCubeHelper::HandleUpdate (this=0x77cee0, eventType=..., eventData=...) at ../../../src/applications/cube_helper/main.cpp:289
А почему вообще вызываются деструкторы? Кто-то бросил исключение?
Здравствуйте, Sheridan, Вы писали:
S>Да, меня тоже это смущает, но я склоняюсь к мысли что дебаггер тут просто показывает место вызова delete в деструкторе.
С другой стороны. Ошибка говорит о том что кто-то помял память.
Можно попробывать вызвть проверку целосности памяти в разных местах что бы локализовать момент разрушения.
Здравствуйте, B0FEE664, Вы писали:
BFE>А почему вообще вызываются деструкторы? Кто-то бросил исключение?
Нет. Просто по событию пришло время удалить объект.
Здравствуйте, Sheridan, Вы писали:
S>Здравствуйте, nekocoder, Вы писали:
S>>>Я же точно знаю время жизни своих объектов. N>>Нет, не знаешь. Поэтому у тебя портится память и ты мучаешься с непонятным крашем. S>У меня не портится. А вот за urho3d не ручаюсь. Достаточно посмотреть на реализацию их "умных" указателей, не к ночи они помянуты будут...
Ты ещё не нашёл ошибку, но уверен, что у тебя память не портиться. Откуда такая уверенность? При ошибках работы с памятью упасть может не там, где память испорчена, а совсем в другом месте.
У тебя не падает при запуске из под валгринда, но падает, когда запускаешь без валгринда. Похоже на неинициализированную переменную или испорченный стек. При сборке в debug и в release программа ведёт себя одинаково? sprintf нигде не используется?
AN>Ты ещё не нашёл ошибку, но уверен, что у тебя память не портиться. Откуда такая уверенность? При ошибках работы с памятью упасть может не там, где память испорчена, а совсем в другом месте.
В своих объектах я уверен просто, пока что не могу себе представить ситуацию когда чтото удалится или создастса невовремя.
AN>У тебя не падает при запуске из под валгринда, но падает, когда запускаешь без валгринда. Похоже на неинициализированную переменную или испорченный стек.
Да, похоже на то. Сегодня еще раз поищу-почитаю как в urho объектами рулить можно. В предыдущие итерации ничего не обнаружил хитрого...
AN>При сборке в debug и в release программа ведёт себя одинаково?
Да.
AN>sprintf нигде не используется?
Нет, только std::out
Здравствуйте, B0FEE664, Вы писали:
S>>Если конечно std::list в remove не вызывает за каким то хреном delete для хранящихся в ём указателей...
BFE>Эээээ..... Чего????
Вот и я так же реагирую. Когда заканчиваются реалистичные идеи — начинаются фанстастические ))
Здравствуйте, Sheridan, Вы писали:
AN>>Ты ещё не нашёл ошибку, но уверен, что у тебя память не портиться. Откуда такая уверенность? При ошибках работы с памятью упасть может не там, где память испорчена, а совсем в другом месте. S>В своих объектах я уверен просто, пока что не могу себе представить ситуацию когда чтото удалится или создастса невовремя.
Учитывая тот код который ты показал, у тебя почти при любом исключении очень большие проблемы с консистентным состоянием объектов.
на форуме много таких которые с ИТ вообще никак не связанны
может он недавно решил #войтивайти
не разобраться с испорченной памятью это задачка уровня джуна
Здравствуйте, reversecode, Вы писали:
R>>>а как давно стали программистом ? R>>>есть мнение что около года-полтора
R>>И тебя не смущает, что он появился на форуме на 13 лет раньше тебя?
R>на форуме много таких которые с ИТ вообще никак не связанны R>может он недавно решил #войтивайти R>не разобраться с испорченной памятью это задачка уровня джуна
Вариант, что С++ просто не совсем его профиль ты не рассматриваешь? А рейтинг он по блату заработал? Модераторы очков наставили, наверное.
Здравствуйте, reversecode, Вы писали:
R>зачем люди занимаются то в чем они не разбираются или разбираются плохо ? R>для этого есть профессионалы R>каждый должен заниматься тем в чем он профи
Здравствуйте, reversecode, Вы писали:
R>зачем люди занимаются то в чем они не разбираются или разбираются плохо ? R>для этого есть профессионалы R>каждый должен заниматься тем в чем он профи
Да мало ли зачем. Хочется ему. Чего ты за него решаешь, чем он должен заниматься.
Здравствуйте, Sheridan, Вы писали:
S>Да, меня тоже это смущает, но я склоняюсь к мысли что дебаггер тут просто показывает место вызова delete в деструкторе.
В таких случаях обычно советуют тупо выключить половину написанного и смотреть, упадет ли. Потом половину от половины в которой падает и т.п. Но у меня так никогда не получалось сделать, так что я оставлял некий минимально не падающий код с подключенными либами и потихоньку включал всё написанное мной назад. Как начинало падать, искал в подключенном.
О чём говорит проверка if(m_blocks.size() && m_parentBlock) ? Я вижу 4 варианта:
1) m_blocks.size() и m_parentBlock — две независимые переменные
2) Sheridan не пользуется assert'ами
3) оптимизация обращения к первому элементу списка
4) проблемы в другом месте кода
судя по коду в removeBlock пункт 1 отпадает. Значит пункты 2-4 реализуются либо совместно, либо по отдельности. Скорее всего m_parentBlock вообще не нужен — это просто первый элемент из списка.
Вас ничего не смущает? Зачем занулять члены класса в деструкторе? Такой приём используют либо новички, либо это хак, который защищает код от падения при обращении к уже разрушенному объекту. (Ну или это статические члены класса, что вряд ли)
Почему m_dynamicMesh — dynamic? Значит где-то есть статик? Т.е. можно предположить, что вызывается delete для переменной не заказанной по new.
Предположим, что m_dynamicMesh — это указатель на CDynamicMesh.
Тогда смотрите:
Если кто-то удаляет объект на который указывает m_dynamicMesh извне деструктора ~CBlock, то
CDynamicMesh::~CDynamicMesh()
{
EING_LOG_DBG_POINT;
if(m_dynamicModel) { EING_ST->graphic()->physicsWorld()->RemoveCachedGeometry(m_dynamicModel); } // Это urho3d, не смотрел что там происходитdelete m_vertexBuffer;
delete m_indexBuffer;
delete m_geometry;
m_podElements.Clear();
if(m_dynamicModel) { delete m_dynamicModel; } // Это urho3d объект, не мой
EING_LOG_DBG_POINT;
}
m_blocks никто не чистит и, соответственно, объекты типа CBlock никто не удаляет — это если предположить, что m_blocks имеет тип std::list<CBlock*>. мы получаем кучу ссылок на убитый объект и утечку памяти.
Если же предположить, что m_blocks — это такой список, который удаляет свои элементы при очистке, то получится ещё интереснее: после выполнения ~CDynamicMesh() начнётся выполнение серии деструкторов ~CBlock, которые попытаются удалить себя из списка находящегося в процессе очистки, а последний элемент ещё и удалит CDynamicMesh второй раз. Так или иначе — ничего хорошего.
Из всего этого следует, что объекты типа CDynamicMesh никогда сами не удаляются. Из этого следует, что на объекты CBlock указатели хранятся где-то снаружи CDynamicMesh и там же уничтожаются. Т.е. мы поняли архитектуру: элементы списка владеют своим списком. Они сами себя из списка удаляют, но добавляют их в список внешним образом:
Вы видите, чтобы block->m_dynamicMesh устанавливался в this в этом методе? Не удивлюсь, если окажется, что recalculate() проходит по списку элементов им устанавливает каждому элементу m_dynamicMesh в this.
Не, ну очевидно, что это код опытного хардкорщика презирающего смарт поинтеры и точно знающего где и что удаляется.
Здравствуйте, B0FEE664, Вы писали:
R>>И тебя не смущает, что он появился на форуме на 13 лет раньше тебя?
BFE>Да какая разница? Код явно низкого качества. BFE> . . .
Так я про код ничего и не говорю. Мне переход на личности не понравился. То, что код не фонтан, меня убеждать нет необходимости
R>>задача valgrind не крошится а показать проблемы с памятью S>Ну так и не показывает
Проблемы с памятью могут быть изза хреновой синхронизации. Валгринд меняет тайминг и волновая функция гейзенбага схлопывается в состояние "бага нет".
Ищи доступ к общей переменной из разных потоков. Сам m_logstream — под первым подозрением. Одновременная запись в него из разных потоков может как раз таким боком вылезти.
Как много веселых ребят, и все делают велосипед...
Тут без вариантов уничтожены внутренние структуры управления памятью, используемые malloc.
Что делать дальше — использовать смарт-поинтеры везде, это может решить проблему с испорченной памятью.
Если нет желания использовать смарт-поинтеры — надо понимать, что имея ту информацию, которая сейчас предоставлена — разрешить проблему невозможно. Нужно иметь и уметь следующие вещи:
— В Вашем gentoo с дебаг-символами и исходниками надо собрать так же glibc.
— Научиться пользоваться valgrind и прогнать программу с под ним.
— Научится читать и понимать дизассемблированный код в gdb, анализировать регистры и память, адреса на которую могут лежать в регистрах, в данном случае неплохо было бы изучить код и память в районе malloc_consolidate — именно там срабатывает assertion в макросе unlink, подозреваю.
Если нет большего желания разбираться с последними тремя пунктами, стоит вернуться к идее со смарт-поинтерами, либо сменить язык разработки.
S>Камрады, ай нид хелп. Не могу понять в чом дело. У меня тут есть логгер, который крашится в рантайме но в дебаге но полезного нет почти. S>При запущенной валгринд с мемчеком — не крашится. S>Принцип такой: при добавлении строки оно открывает ofstream в файл, пишет туда строку, закрывает. S>Крашится как раз на открытии ofstream S>
S>m_filename — std::string S>m_logstream — std::ofstream
S>Через раз показывает причину: S>
S>malloc_consolidate(): invalid chunk size
S>
S>Я предполагал что это краш в другом потоке, но уже дважды всё там переписал — не должно S>Ну и крашится на вызове логгера из деструктора объекта. При этом оно к объекту самому разрушаемому не обращается S>сам логгер — синглтон, создаётся при первом обращении, удаляется при выходе из приложения
S>Полный стек вызовов, крашится в Thread 1: S>
S>Thread 7 (Thread 0x7fffc68e1700 (LWP 31402)):
S>#0 0x00007ffff595b6c6 in ppoll () from /lib64/libc.so.6
S>No symbol table info available.
S>#1 0x00007ffff36ab901 in pa_mainloop_poll () from /usr/lib64/libpulse.so.0
S>No symbol table info available.
S>#2 0x00007ffff36abf10 in pa_mainloop_iterate () from /usr/lib64/libpulse.so.0
S>No symbol table info available.
S>#3 0x00007ffff780c2a7 in PULSEAUDIO_WaitDevice () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#4 0x00007ffff779442e in SDL_RunAudio () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#5 0x00007ffff779375c in SDL_RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#6 0x00007ffff7809ac9 in RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#7 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#8 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>No symbol table info available.
S>Thread 6 (Thread 0x7fffd72e2700 (LWP 31401)):
S>#0 0x00007ffff5c3d30c in __lll_lock_wait () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#1 0x00007ffff5c357a2 in pthread_mutex_lock () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#2 0x00007ffff73401cf in Urho3D::WorkQueue::ProcessItems(unsigned int) () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#3 0x00007ffff7339f1a in Urho3D::ThreadFunctionStatic(void*) () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#4 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#5 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>No symbol table info available.
S>Thread 5 (Thread 0x7fffd7ae3700 (LWP 31400)):
S>#0 0x00007ffff5c3d30c in __lll_lock_wait () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#1 0x00007ffff5c357a2 in pthread_mutex_lock () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#2 0x00007ffff73401cf in Urho3D::WorkQueue::ProcessItems(unsigned int) () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#3 0x00007ffff7339f1a in Urho3D::ThreadFunctionStatic(void*) () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#4 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#5 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>No symbol table info available.
S>Thread 4 (Thread 0x7fffd82e4700 (LWP 31399)):
S>#0 0x00007ffff5c3d30c in __lll_lock_wait () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#1 0x00007ffff5c357a2 in pthread_mutex_lock () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#2 0x00007ffff73401cf in Urho3D::WorkQueue::ProcessItems(unsigned int) () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#3 0x00007ffff7339f1a in Urho3D::ThreadFunctionStatic(void*) () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#4 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#5 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>No symbol table info available.
S>Thread 3 (Thread 0x7fffdbfff700 (LWP 31398)):
S>#0 0x00007ffff5c3e138 in nanosleep () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#1 0x00000000004b0f90 in std::this_thread::sleep_for<long, std::ratio<1l, 1000l> > (__rtime=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:376
S> __s = {__r = 0}
S> __ns = {__r = 100000000}
S> __ts = {tv_sec = 0, tv_nsec = 36163799}
S>#2 0x00000000004b06b5 in eing::world::CWorld::worldThread (this=0x7b4640) at ../../../src/world/cworld.cpp:89
S>No locals.
S>#3 0x00000000004b2e41 in std::__invoke_impl<void, void (eing::world::CWorld::*)(), eing::world::CWorld*> (__f=@0x839ac0: (void (eing::world::CWorld::*)(eing::world::CWorld * const)) 0x4b0660 <eing::world::CWorld::worldThread()>, __t=@0x839ab8: 0x7b4640) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/invoke.h:73
S>No locals.
S>#4 0x00000000004b2d52 in std::__invoke<void (eing::world::CWorld::*)(), eing::world::CWorld*> (__fn=@0x839ac0: (void (eing::world::CWorld::*)(eing::world::CWorld * const)) 0x4b0660 <eing::world::CWorld::worldThread()>, __args=@0x839ab8: 0x7b4640) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/invoke.h:95
S>No locals.
S>#5 0x00000000004b2d12 in std::thread::_Invoker<std::tuple<void (eing::world::CWorld::*)(), eing::world::CWorld*> >::_M_invoke<0ul, 1ul> (this=0x839ab8) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:234
S>No locals.
S>#6 0x00000000004b2cc5 in std::thread::_Invoker<std::tuple<void (eing::world::CWorld::*)(), eing::world::CWorld*> >::operator() (this=0x839ab8) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:243
S>No locals.
S>#7 0x00000000004b2a99 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (eing::world::CWorld::*)(), eing::world::CWorld*> > >::_M_run (this=0x839ab0) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:186
S>No locals.
S>#8 0x00007ffff6142f0e in std::execute_native_thread_routine (__p=0x839ab0) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/src/c++11/thread.cc:83
S> __t = {_M_t = {_M_t = {<std::_Tuple_impl<0, std::thread::_State*, std::default_delete<std::thread::_State> >> = {<std::_Tuple_impl<1, std::default_delete<std::thread::_State> >> = {<std::_Head_base<1, std::default_delete<std::thread::_State>, true>> = {<std::default_delete<std::thread::_State>> = {<No data fields>}, <No data fields>}, <No data fields>}, <std::_Head_base<0, std::thread::_State*, false>> = {_M_head_impl = 0x839ab0}, <No data fields>}, <No data fields>}}}
S>#9 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#10 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>No symbol table info available.
S>Thread 2 (Thread 0x7ffff7fed700 (LWP 31397)):
S>#0 0x00007ffff595b6c6 in ppoll () from /lib64/libc.so.6
S>No symbol table info available.
S>#1 0x00007ffff36ab901 in pa_mainloop_poll () from /usr/lib64/libpulse.so.0
S>No symbol table info available.
S>#2 0x00007ffff36abf10 in pa_mainloop_iterate () from /usr/lib64/libpulse.so.0
S>No symbol table info available.
S>#3 0x00007ffff36abfa0 in pa_mainloop_run () from /usr/lib64/libpulse.so.0
S>No symbol table info available.
S>#4 0x00007ffff780c40f in HotplugThread () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#5 0x00007ffff779375c in SDL_RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#6 0x00007ffff7809ac9 in RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#7 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>No symbol table info available.
S>#8 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>No symbol table info available.
S>Thread 1 (Thread 0x7ffff7f830c0 (LWP 31391)):
S>#0 0x00007ffff589976b in raise () from /lib64/libc.so.6
S>No symbol table info available.
S>#1 0x00007ffff589afb1 in abort () from /lib64/libc.so.6
S>No symbol table info available.
S>#2 0x00007ffff58e02e7 in __libc_message () from /lib64/libc.so.6
S>No symbol table info available.
S>#3 0x00007ffff58e8038 in malloc_printerr () from /lib64/libc.so.6
S>No symbol table info available.
S>#4 0x00007ffff58e83be in malloc_consolidate () from /lib64/libc.so.6
S>No symbol table info available.
S>#5 0x00007ffff58eb1d8 in _int_malloc () from /lib64/libc.so.6
S>No symbol table info available.
S>#6 0x00007ffff58eceaa in malloc () from /lib64/libc.so.6
S>No symbol table info available.
S>#7 0x00007ffff6116418 in operator new (sz=8192) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/libsupc++/new_op.cc:50
S> p = <optimized out>
S>#8 0x00007ffff61164c5 in operator new[] (sz=<optimized out>) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/libsupc++/new_opv.cc:32
S>No locals.
S>#9 0x00007ffff617b6f8 in std::basic_filebuf<char, std::char_traits<char> >::_M_allocate_internal_buffer (this=0x794ec8) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:55
S> this = 0x794ec8
S>#10 0x00007ffff617fd12 in std::basic_filebuf<char, std::char_traits<char> >::open (this=0x794ec8, __s=0x795800 "logs/cube_helper/2018-12-16_18-12-02.application.log", __mode=19) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:187
S> __ret = 0x0
S> __s = 0x795800 "logs/cube_helper/2018-12-16_18-12-02.application.log"
S> __mode = 19
S> this = 0x794ec8
S> __ret = <optimized out>
S> __ret = 0x0
S>#11 0x00007ffff617fe43 in std::basic_filebuf<char, std::char_traits<char> >::open (__mode=<optimized out>, __s=..., this=0x794ec8) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/fstream:308
S>No locals.
S>#12 std::basic_ofstream<char, std::char_traits<char> >::open (this=0x794ec0, __s=..., __mode=<optimized out>) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/fstream:823
S>No locals.
S>#13 0x00000000004aef98 in eing::tools::logger::CLogger::start (this=0x794e80) at ../../../src/tools/logger/clogger.cpp:63
S> time = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7958d0 "P\223\330\367\377\177"}, _M_string_length = 7949920, {_M_local_buf = "\320\\y\000\000\000\000\000\200\006\365\000\000\000\000", _M_allocated_capacity = 7953616}}
S>#14 0x00000000004cc16d in eing::graphic::world::CDynamicMesh::~CDynamicMesh (this=0x1073aa0) at ../../../src/graphic/world/cdynamicmesh.cpp:40
S>No locals.
S>#15 0x000000000049692e in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:48
S>No locals.
S>#16 0x0000000000496c89 in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:41
S>No locals.
S>#17 0x000000000045c05f in eing_helper::cube::AppCubeHelper::redrawTestCube (this=0x77cee0) at ../../../src/applications/cube_helper/main.cpp:350
S> e = @0xae6100: {_vptr.exception = 0xae61b0}
S>#18 0x000000000045d2af in eing_helper::cube::AppCubeHelper::HandleUpdate (this=0x77cee0, eventType=..., eventData=...) at ../../../src/applications/cube_helper/main.cpp:289
S> yaw_ = 0
S> pitch_ = 0
S> timeStep = 0.00499999989
S> MOVE_SPEED = 10
S> MOUSE_SENSITIVITY = 0.100000001
S>#19 0x0000000000460bc7 in Urho3D::EventHandlerImpl<eing_helper::cube::AppCubeHelper>::Invoke (this=0x106aff0, eventData=...) at /usr/include/Urho3D/Physics/../Core/Object.h:315
S> receiver = 0x77cee0
S>#20 0x00007ffff732d642 in Urho3D::Object::OnEvent(Urho3D::Object*, Urho3D::StringHash, Urho3D::HashMap<Urho3D::StringHash, Urho3D::Variant>&) () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#21 0x00007ffff732e93f in Urho3D::Object::SendEvent(Urho3D::StringHash, Urho3D::HashMap<Urho3D::StringHash, Urho3D::Variant>&) () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#22 0x00007ffff734d1d7 in Urho3D::Engine::Update() () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#23 0x00007ffff735013a in Urho3D::Engine::RunFrame() () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#24 0x00007ffff7342e45 in Urho3D::Application::Run() () from /usr/lib/Urho3D/libUrho3D.so.0
S>No symbol table info available.
S>#25 0x000000000045d44a in main (argc=1, argv=0x7fffffffe018) at ../../../src/applications/cube_helper/main.cpp:378
S> graphic_result = 0
S>
S>Накидайте идей что это может быть? Может уже встречалось такое?...
Здравствуйте, B0FEE664, Вы писали:
BFE>Вас ничего не смущает? Зачем занулять члены класса в деструкторе? Такой приём используют либо новички, либо это хак, который защищает код от падения при обращении к уже разрушенному объекту. (Ну или это статические члены класса, что вряд ли)
Указатель обязан быть в двух состояниях: рабочий и nullptr. Но в деструкторе так сейчас потому как код туда переехал из другого метода. просто не убрал лишние присваивания.
BFE>Почему m_dynamicMesh — dynamic? Значит где-то есть статик? Т.е. можно предположить, что вызывается delete для переменной не заказанной по new.
Нет. Потому что это динамический (изменяющийся со временем по разным причинам) mesh.
BFE>Предположим, что m_dynamicMesh — это указатель на CDynamicMesh. BFE>Тогда смотрите: BFE>Если кто-то удаляет объект на который указывает m_dynamicMesh извне деструктора ~CBlock, то
Никто этого сделать не может, потому как никому кроме cblock этот динамикмеш не нужен и про него вообще знает только cblock.
BFE>m_blocks никто не чистит и, соответственно, объекты типа CBlock никто не удаляет — это если предположить, что m_blocks имеет тип std::list<CBlock*>. мы получаем кучу ссылок на убитый объект и утечку памяти.
m_blocks никто не чистит потому как динамикмеш зависит от cblock а не наоборот. Родидился блок — добавился в меш. Умер — удалился. Последний умерший забирает с собой в могилу и динамикмеш.
BFE>Если же предположить, что m_blocks — это такой список, который удаляет свои элементы при очистке, то получится ещё интереснее: после выполнения ~CDynamicMesh() начнётся выполнение серии деструкторов ~CBlock, которые попытаются удалить себя из списка находящегося в процессе очистки, а последний элемент ещё и удалит CDynamicMesh второй раз. Так или иначе — ничего хорошего.
Нет, неверное предположение. Дважды динамикмеш не удалится ибо эта штука работает только с cblock.
BFE>Из всего этого следует, что объекты типа CDynamicMesh никогда сами не удаляются. Из этого следует, что на объекты CBlock указатели хранятся где-то снаружи CDynamicMesh и там же уничтожаются. Т.е. мы поняли архитектуру: элементы списка владеют своим списком. Они сами себя из списка удаляют, но добавляют их в список внешним образом:
Когда блок рождается — он спрашивает соседей про их свойства. При совпадении некоторых свойств блок понимает что самостоятельно отрисовываться будет тяжело и запрашивает у соседа ссылку на динамикмеш, в который добавляет себя. Динамикмеш занимается тем что создаёт одну ноду на множество блоков.
Время жизни блоков разное зависит от разных факторов. При удалении блока он сообщает мешу о своей смерти. И когда, сообщив, видит что меш осиротел — забирает его с собой.
BFE>Вы видите, чтобы block->m_dynamicMesh устанавливался в this в этом методе? Не удивлюсь, если окажется, что recalculate() проходит по списку элементов им устанавливает каждому элементу m_dynamicMesh в this.
Нет. В recalculate расчитываются вершины и индексы получающейся фигуры и фигура закидывается в модель чтобы рендерилось.
BFE>Не, ну очевидно, что это код опытного хардкорщика презирающего смарт поинтеры и точно знающего где и что удаляется.
Точно знаю, да.
m_dynamicMesh объявлена как static?
m_dynamicMesh инициализируется в CBlock::CBlock()?
Работа с CBlock потокобезопасная? Может ли CBlock::CBlock() и CBlock::~CBlock() дёрнуться из разных потоков?
Здравствуйте, B0FEE664, Вы писали:
BFE>Метод logger() не является потокобезопасным. Если он вызывается из двух и более ниток, то может быть создано два и более объектов типа CLogger. Переделал всё это на
Но всё равно не помогает. Хотя, судя по дебагу, и старый вариант не плодил экземпляры, а пользовал один и тот же. Поэтому не пошел дальше и не стал на std::call_once переделывать.
Здравствуйте, Sheridan, Вы писали:
BFE>>Из всего этого следует, что объекты типа CDynamicMesh никогда сами не удаляются. Из этого следует, что на объекты CBlock указатели хранятся где-то снаружи CDynamicMesh и там же уничтожаются. Т.е. мы поняли архитектуру: элементы списка владеют своим списком. Они сами себя из списка удаляют, но добавляют их в список внешним образом: S>Когда блок рождается — он спрашивает соседей про их свойства. При совпадении некоторых свойств блок понимает что самостоятельно отрисовываться будет тяжело и запрашивает у соседа ссылку на динамикмеш, в который добавляет себя. Динамикмеш занимается тем что создаёт одну ноду на множество блоков. S>Время жизни блоков разное зависит от разных факторов. При удалении блока он сообщает мешу о своей смерти. И когда, сообщив, видит что меш осиротел — забирает его с собой.
Значит я всё правильно понял. Если block->m_dynamicMesh везде правильно установлен и сам динамикмеш нигде не удаляется, то может это и будет работать...
Какой, всё же, тип у CDynamicMesh::m_blocks?
BFE>>Вы видите, чтобы block->m_dynamicMesh устанавливался в this в этом методе? Не удивлюсь, если окажется, что recalculate() проходит по списку элементов им устанавливает каждому элементу m_dynamicMesh в this. S>Нет. В recalculate расчитываются вершины и индексы получающейся фигуры и фигура закидывается в модель чтобы рендерилось.
А где m_dynamicMesh присваивается?
Ну и, после исследования сорсов glibc в районе malloc, надо будет понять, какое место в памяти портится, при последующих запусках на более ранних этапах выяснить новый адрес потенциально интересного куска, и сделать в gdb watch *0x00fffe — этого адреса.
так же, интересна выдача valgrind — в С++ не бывает проблем в чужом коде, адресное пространство общее, в таком случае обязан был показать проблему valgrind.
Z>Здравствуйте, Sheridan, Вы писали:
Z>Тут без вариантов уничтожены внутренние структуры управления памятью, используемые malloc.
Z>Что делать дальше — использовать смарт-поинтеры везде, это может решить проблему с испорченной памятью. Z>Если нет желания использовать смарт-поинтеры — надо понимать, что имея ту информацию, которая сейчас предоставлена — разрешить проблему невозможно. Нужно иметь и уметь следующие вещи:
Z>- В Вашем gentoo с дебаг-символами и исходниками надо собрать так же glibc. Z>- Научиться пользоваться valgrind и прогнать программу с под ним. Z>- Научится читать и понимать дизассемблированный код в gdb, анализировать регистры и память, адреса на которую могут лежать в регистрах, в данном случае неплохо было бы изучить код и память в районе malloc_consolidate — именно там срабатывает assertion в макросе unlink, подозреваю.
Z>Если нет большего желания разбираться с последними тремя пунктами, стоит вернуться к идее со смарт-поинтерами, либо сменить язык разработки.
S>>Камрады, ай нид хелп. Не могу понять в чом дело. У меня тут есть логгер, который крашится в рантайме но в дебаге но полезного нет почти. S>>При запущенной валгринд с мемчеком — не крашится. S>>Принцип такой: при добавлении строки оно открывает ofstream в файл, пишет туда строку, закрывает. S>>Крашится как раз на открытии ofstream S>>
S>>m_filename — std::string S>>m_logstream — std::ofstream
S>>Через раз показывает причину: S>>
S>>malloc_consolidate(): invalid chunk size
S>>
S>>Я предполагал что это краш в другом потоке, но уже дважды всё там переписал — не должно S>>Ну и крашится на вызове логгера из деструктора объекта. При этом оно к объекту самому разрушаемому не обращается S>>сам логгер — синглтон, создаётся при первом обращении, удаляется при выходе из приложения
S>>Полный стек вызовов, крашится в Thread 1: S>>
S>>Thread 7 (Thread 0x7fffc68e1700 (LWP 31402)):
S>>#0 0x00007ffff595b6c6 in ppoll () from /lib64/libc.so.6
S>>No symbol table info available.
S>>#1 0x00007ffff36ab901 in pa_mainloop_poll () from /usr/lib64/libpulse.so.0
S>>No symbol table info available.
S>>#2 0x00007ffff36abf10 in pa_mainloop_iterate () from /usr/lib64/libpulse.so.0
S>>No symbol table info available.
S>>#3 0x00007ffff780c2a7 in PULSEAUDIO_WaitDevice () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#4 0x00007ffff779442e in SDL_RunAudio () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#5 0x00007ffff779375c in SDL_RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#6 0x00007ffff7809ac9 in RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#7 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#8 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>>No symbol table info available.
S>>Thread 6 (Thread 0x7fffd72e2700 (LWP 31401)):
S>>#0 0x00007ffff5c3d30c in __lll_lock_wait () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#1 0x00007ffff5c357a2 in pthread_mutex_lock () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#2 0x00007ffff73401cf in Urho3D::WorkQueue::ProcessItems(unsigned int) () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#3 0x00007ffff7339f1a in Urho3D::ThreadFunctionStatic(void*) () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#4 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#5 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>>No symbol table info available.
S>>Thread 5 (Thread 0x7fffd7ae3700 (LWP 31400)):
S>>#0 0x00007ffff5c3d30c in __lll_lock_wait () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#1 0x00007ffff5c357a2 in pthread_mutex_lock () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#2 0x00007ffff73401cf in Urho3D::WorkQueue::ProcessItems(unsigned int) () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#3 0x00007ffff7339f1a in Urho3D::ThreadFunctionStatic(void*) () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#4 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#5 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>>No symbol table info available.
S>>Thread 4 (Thread 0x7fffd82e4700 (LWP 31399)):
S>>#0 0x00007ffff5c3d30c in __lll_lock_wait () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#1 0x00007ffff5c357a2 in pthread_mutex_lock () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#2 0x00007ffff73401cf in Urho3D::WorkQueue::ProcessItems(unsigned int) () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#3 0x00007ffff7339f1a in Urho3D::ThreadFunctionStatic(void*) () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#4 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#5 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>>No symbol table info available.
S>>Thread 3 (Thread 0x7fffdbfff700 (LWP 31398)):
S>>#0 0x00007ffff5c3e138 in nanosleep () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#1 0x00000000004b0f90 in std::this_thread::sleep_for<long, std::ratio<1l, 1000l> > (__rtime=...) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:376
S>> __s = {__r = 0}
S>> __ns = {__r = 100000000}
S>> __ts = {tv_sec = 0, tv_nsec = 36163799}
S>>#2 0x00000000004b06b5 in eing::world::CWorld::worldThread (this=0x7b4640) at ../../../src/world/cworld.cpp:89
S>>No locals.
S>>#3 0x00000000004b2e41 in std::__invoke_impl<void, void (eing::world::CWorld::*)(), eing::world::CWorld*> (__f=@0x839ac0: (void (eing::world::CWorld::*)(eing::world::CWorld * const)) 0x4b0660 <eing::world::CWorld::worldThread()>, __t=@0x839ab8: 0x7b4640) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/invoke.h:73
S>>No locals.
S>>#4 0x00000000004b2d52 in std::__invoke<void (eing::world::CWorld::*)(), eing::world::CWorld*> (__fn=@0x839ac0: (void (eing::world::CWorld::*)(eing::world::CWorld * const)) 0x4b0660 <eing::world::CWorld::worldThread()>, __args=@0x839ab8: 0x7b4640) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/bits/invoke.h:95
S>>No locals.
S>>#5 0x00000000004b2d12 in std::thread::_Invoker<std::tuple<void (eing::world::CWorld::*)(), eing::world::CWorld*> >::_M_invoke<0ul, 1ul> (this=0x839ab8) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:234
S>>No locals.
S>>#6 0x00000000004b2cc5 in std::thread::_Invoker<std::tuple<void (eing::world::CWorld::*)(), eing::world::CWorld*> >::operator() (this=0x839ab8) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:243
S>>No locals.
S>>#7 0x00000000004b2a99 in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (eing::world::CWorld::*)(), eing::world::CWorld*> > >::_M_run (this=0x839ab0) at /usr/lib/gcc/x86_64-pc-linux-gnu/7.3.0/include/g++-v7/thread:186
S>>No locals.
S>>#8 0x00007ffff6142f0e in std::execute_native_thread_routine (__p=0x839ab0) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/src/c++11/thread.cc:83
S>> __t = {_M_t = {_M_t = {<std::_Tuple_impl<0, std::thread::_State*, std::default_delete<std::thread::_State> >> = {<std::_Tuple_impl<1, std::default_delete<std::thread::_State> >> = {<std::_Head_base<1, std::default_delete<std::thread::_State>, true>> = {<std::default_delete<std::thread::_State>> = {<No data fields>}, <No data fields>}, <No data fields>}, <std::_Head_base<0, std::thread::_State*, false>> = {_M_head_impl = 0x839ab0}, <No data fields>}, <No data fields>}}}
S>>#9 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#10 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>>No symbol table info available.
S>>Thread 2 (Thread 0x7ffff7fed700 (LWP 31397)):
S>>#0 0x00007ffff595b6c6 in ppoll () from /lib64/libc.so.6
S>>No symbol table info available.
S>>#1 0x00007ffff36ab901 in pa_mainloop_poll () from /usr/lib64/libpulse.so.0
S>>No symbol table info available.
S>>#2 0x00007ffff36abf10 in pa_mainloop_iterate () from /usr/lib64/libpulse.so.0
S>>No symbol table info available.
S>>#3 0x00007ffff36abfa0 in pa_mainloop_run () from /usr/lib64/libpulse.so.0
S>>No symbol table info available.
S>>#4 0x00007ffff780c40f in HotplugThread () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#5 0x00007ffff779375c in SDL_RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#6 0x00007ffff7809ac9 in RunThread () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#7 0x00007ffff5c3296a in start_thread () from /lib64/libpthread.so.0
S>>No symbol table info available.
S>>#8 0x00007ffff59671af in clone () from /lib64/libc.so.6
S>>No symbol table info available.
S>>Thread 1 (Thread 0x7ffff7f830c0 (LWP 31391)):
S>>#0 0x00007ffff589976b in raise () from /lib64/libc.so.6
S>>No symbol table info available.
S>>#1 0x00007ffff589afb1 in abort () from /lib64/libc.so.6
S>>No symbol table info available.
S>>#2 0x00007ffff58e02e7 in __libc_message () from /lib64/libc.so.6
S>>No symbol table info available.
S>>#3 0x00007ffff58e8038 in malloc_printerr () from /lib64/libc.so.6
S>>No symbol table info available.
S>>#4 0x00007ffff58e83be in malloc_consolidate () from /lib64/libc.so.6
S>>No symbol table info available.
S>>#5 0x00007ffff58eb1d8 in _int_malloc () from /lib64/libc.so.6
S>>No symbol table info available.
S>>#6 0x00007ffff58eceaa in malloc () from /lib64/libc.so.6
S>>No symbol table info available.
S>>#7 0x00007ffff6116418 in operator new (sz=8192) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/libsupc++/new_op.cc:50
S>> p = <optimized out>
S>>#8 0x00007ffff61164c5 in operator new[] (sz=<optimized out>) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/gcc-7.3.0/libstdc++-v3/libsupc++/new_opv.cc:32
S>>No locals.
S>>#9 0x00007ffff617b6f8 in std::basic_filebuf<char, std::char_traits<char> >::_M_allocate_internal_buffer (this=0x794ec8) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:55
S>> this = 0x794ec8
S>>#10 0x00007ffff617fd12 in std::basic_filebuf<char, std::char_traits<char> >::open (this=0x794ec8, __s=0x795800 "logs/cube_helper/2018-12-16_18-12-02.application.log", __mode=19) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/bits/fstream.tcc:187
S>> __ret = 0x0
S>> __s = 0x795800 "logs/cube_helper/2018-12-16_18-12-02.application.log"
S>> __mode = 19
S>> this = 0x794ec8
S>> __ret = <optimized out>
S>> __ret = 0x0
S>>#11 0x00007ffff617fe43 in std::basic_filebuf<char, std::char_traits<char> >::open (__mode=<optimized out>, __s=..., this=0x794ec8) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/fstream:308
S>>No locals.
S>>#12 std::basic_ofstream<char, std::char_traits<char> >::open (this=0x794ec0, __s=..., __mode=<optimized out>) at /data/tmp/portage/sys-devel/gcc-7.3.0-r3/work/build/x86_64-pc-linux-gnu/libstdc++-v3/include/fstream:823
S>>No locals.
S>>#13 0x00000000004aef98 in eing::tools::logger::CLogger::start (this=0x794e80) at ../../../src/tools/logger/clogger.cpp:63
S>> time = {static npos = 18446744073709551615, _M_dataplus = {<std::allocator<char>> = {<__gnu_cxx::new_allocator<char>> = {<No data fields>}, <No data fields>}, _M_p = 0x7958d0 "P\223\330\367\377\177"}, _M_string_length = 7949920, {_M_local_buf = "\320\\y\000\000\000\000\000\200\006\365\000\000\000\000", _M_allocated_capacity = 7953616}}
S>>#14 0x00000000004cc16d in eing::graphic::world::CDynamicMesh::~CDynamicMesh (this=0x1073aa0) at ../../../src/graphic/world/cdynamicmesh.cpp:40
S>>No locals.
S>>#15 0x000000000049692e in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:48
S>>No locals.
S>>#16 0x0000000000496c89 in eing::graphic::world::CBlock::~CBlock (this=0x105d070) at ../../../src/graphic/world/cblock.cpp:41
S>>No locals.
S>>#17 0x000000000045c05f in eing_helper::cube::AppCubeHelper::redrawTestCube (this=0x77cee0) at ../../../src/applications/cube_helper/main.cpp:350
S>> e = @0xae6100: {_vptr.exception = 0xae61b0}
S>>#18 0x000000000045d2af in eing_helper::cube::AppCubeHelper::HandleUpdate (this=0x77cee0, eventType=..., eventData=...) at ../../../src/applications/cube_helper/main.cpp:289
S>> yaw_ = 0
S>> pitch_ = 0
S>> timeStep = 0.00499999989
S>> MOVE_SPEED = 10
S>> MOUSE_SENSITIVITY = 0.100000001
S>>#19 0x0000000000460bc7 in Urho3D::EventHandlerImpl<eing_helper::cube::AppCubeHelper>::Invoke (this=0x106aff0, eventData=...) at /usr/include/Urho3D/Physics/../Core/Object.h:315
S>> receiver = 0x77cee0
S>>#20 0x00007ffff732d642 in Urho3D::Object::OnEvent(Urho3D::Object*, Urho3D::StringHash, Urho3D::HashMap<Urho3D::StringHash, Urho3D::Variant>&) () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#21 0x00007ffff732e93f in Urho3D::Object::SendEvent(Urho3D::StringHash, Urho3D::HashMap<Urho3D::StringHash, Urho3D::Variant>&) () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#22 0x00007ffff734d1d7 in Urho3D::Engine::Update() () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#23 0x00007ffff735013a in Urho3D::Engine::RunFrame() () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#24 0x00007ffff7342e45 in Urho3D::Application::Run() () from /usr/lib/Urho3D/libUrho3D.so.0
S>>No symbol table info available.
S>>#25 0x000000000045d44a in main (argc=1, argv=0x7fffffffe018) at ../../../src/applications/cube_helper/main.cpp:378
S>> graphic_result = 0
S>>
S>>Накидайте идей что это может быть? Может уже встречалось такое?...
Здравствуйте, B0FEE664, Вы писали:
S>>Время жизни блоков разное зависит от разных факторов. При удалении блока он сообщает мешу о своей смерти. И когда, сообщив, видит что меш осиротел — забирает его с собой.
BFE>Значит я всё правильно понял. Если block->m_dynamicMesh везде правильно установлен и сам динамикмеш нигде не удаляется, то может это и будет работать... BFE>Какой, всё же, тип у CDynamicMesh::m_blocks?
std::list<cblock *>
BFE>>>Вы видите, чтобы block->m_dynamicMesh устанавливался в this в этом методе? Не удивлюсь, если окажется, что recalculate() проходит по списку элементов им устанавливает каждому элементу m_dynamicMesh в this. S>>Нет. В recalculate расчитываются вершины и индексы получающейся фигуры и фигура закидывается в модель чтобы рендерилось. BFE>А где m_dynamicMesh присваивается?
В кострукторе cblock. Точнее в методе, который вызывается исключительно из конструктора, но это уже детали реализации.
AN>m_dynamicMesh объявлена как static?
Нет. AN>m_dynamicMesh инициализируется в CBlock::CBlock()?
Да. AN>Работа с CBlock потокобезопасная? Может ли CBlock::CBlock() и CBlock::~CBlock() дёрнуться из разных потоков?
Нет.
Дело было не в бобине.
Похоже, внутри urho3d отсутствуют проверки внутри их "умных" указателей. Причём они, похоже, это монго встроили везде куда могли дотянуться.
Что делаю:
class cobject
{
cobject () { buf = new urho3d::vertexbyffer(); }
~cobject () { delete buf; }
urho3d::vertexbyffer *buf;
}
Казалось бы — валидный код. Ан нет, нифига подобного. У них почти любой объект — refcounted, в том числе и этот вертексбуффер. В результате валится в ReleaseRef(); внутри urho
Далее, интерфейсы SetVertexBuffer и SetIndexBuffer явно указывают на утечки памяти, если не удалять самостоятельно. Собственно вот поэтому и рулил сам.
И на самом деле я до сих пор сомневаюсь что там нет утечек.
Здравствуйте, Sheridan, Вы писали:
S>Дело было не в бобине. S>Похоже, внутри urho3d отсутствуют проверки внутри их "умных" указателей. Причём они, похоже, это монго встроили везде куда могли дотянуться. S>Что делаю: S>
S>Казалось бы — валидный код. Ан нет, нифига подобного. У них почти любой объект — refcounted, в том числе и этот вертексбуффер. В результате валится в ReleaseRef(); внутри urho S>Далее, интерфейсы SetVertexBuffer и SetIndexBuffer явно указывают на утечки памяти, если не удалять самостоятельно. Собственно вот поэтому и рулил сам. S>И на самом деле я до сих пор сомневаюсь что там нет утечек.
Правильно, потому, что у них любой класс, в том числе и этот вертексбуффер, заточен на использование с их умным указателем: Urho3D::SharedPtr. И выглядеть это, по их задумке, должно бы примерно так:
class cobject
{
public:
cobject() : m_vertex_buffer_ptr(new Urho3D::VertexBuffer()) {}
virtual ~cobject() { /*nothing to do*/ }
private:
Urho3D::SharedPtr<Urho3D::VertexBuffer> m_vertex_buffer_ptr;
};
Сделай ты так сразу, сэкономил бы кучу времени. Но ты же легких путей не ищещь и, вместо того, чтобы воспользоваться готовым умным указателем, ты, по факту, каждый свой класс превратил в умный указатель. Вот только подсчетом ссылок заморачиваться не стал. Вот и получил заслуженную "награду".
Здравствуйте, rg45, Вы писали:
R>Сделай ты так сразу, сэкономил бы кучу времени. Но ты же легких путей не ищещь и, вместо того, чтобы воспользоваться готовым умным указателем,
Потому что это монго к коду лучше не подпускать. В чём я лишний раз убедился на практике.
R>ты, по факту, каждый свой класс превратил в умный указатель. Вот только подсчетом ссылок заморачиваться не стал. Вот и получил заслуженную "награду".
С каких пор инкапсуляция стала "умным указателем"? Подсчёт ссылок мне не нужен, потому что у меня указателей ровно один (на каждый нужный тип), и он либо указатель, либо nullptr
А урхопрограммеры даже не удосужились проверять на nullptr.
Здравствуйте, Sheridan, Вы писали:
S>С каких пор инкапсуляция стала "умным указателем"? Подсчёт ссылок мне не нужен, потому что у меня указателей ровно один (на каждый нужный тип), и он либо указатель, либо nullptr
Просто инкапсуляция, конечно, нет. А вот для того, чтобы обеспечить совместное владение объектом ПРАВИЛЬНО, у тебя нет другого выхода, кроме как продублировать всю люгику работы умного указателя в каждом своем классе.
S>А урхопрограммеры даже не удосужились проверять на nullptr.
А как они могут проверить, что ты обнулил где-то там какой-то свой указатель? У них на этот же самый объект одновременно указывает еще дюжина других указателей. И удалить объект можно, только вместе с инвалидацией последнего указателя. И добиться этого можно, только через совместный подсчет ссылок.
Но у тебя иная ситуация — ты создал объект и в какой-то момент передаешь его в библиотечную функцию (на отрисовку, например). Библиотека сразу же захватывает владение этим объектом при помощи умного указателя (увеличивает счетчит ссылок). А по окончании работы освобождает объект от владения, уменьшает счетчик ссылок и, при достиженни счетчиком нуля грохает объект. Ты ведь счетчик ссылок не нарастил, поэтому про твое владение объектом никто ничего не знает.
И я хочу привести еще один довод в пользу умных указателей. Представь, что в каком-то классе у тебя оказалось два инкапсулированных указателя. Может такое быть? И вот, ты успешно создаешь первый объект, а при создании второго летит исключение. И приехали, первый объект никто никогда не освободит, потому, что деструктор в таких случаях не вызывается.
Здравствуйте, rg45, Вы писали:
S>>С каких пор инкапсуляция стала "умным указателем"? Подсчёт ссылок мне не нужен, потому что у меня указателей ровно один (на каждый нужный тип), и он либо указатель, либо nullptr R>Просто инкапсуляция, конечно, нет. А вот для того, чтобы обеспечить совместное владение объектом ПРАВИЛЬНО, у тебя нет другого выхода, кроме как продублировать всю люгику работы умного указателя в каждом своем классе.
У меня совместное владение ровно одно пока что на проект и там всё ровно.
S>>А урхопрограммеры даже не удосужились проверять на nullptr. R>А как они могут проверить, что ты обнулил где-то там какой-то свой указатель?
if(!rawptr) { /*оппа, указателя больше нет!*/ }
R>Но у тебя иная ситуация — ты создал объект и в какой-то момент передаешь его в библиотечную функцию (на отрисовку, например). Библиотека сразу же захватывает владение этим объектом при помощи умного указателя (увеличивает счетчит ссылок). А по окончании работы освобождает объект от владения, уменьшает счетчик ссылок и, при достиженни счетчиком нуля грохает объект. Ты ведь счетчик ссылок не нарастил, поэтому про твое владение объектом никто ничего не знает.
Понимаеш ли, у них есть специальный SharedPtr и они всегда явно создают объект с ним например так
SharedPtr<Node> node = scene->createChild();
И чтобы догадаться что
Node *node = scene->createChild();
не совсем и указатель нормальный, а половина умного, то нужно ну я не знаю, телепатом быть, чтоли. Или сорцы библиотеки сначала почитать.
Нормальный человек смотрит на код в первом примере и думает "А, ну тут шаред. Чтобы получить обычный указатель, нужно просто без шаред обёртки" и бинго, креш на ровном месте.
Вот как так можно было написать, а? Хотите шаред сделать — да магистры с вам, делайте. Но нафига в шаред реализовывать первую часть и в остальных объектах вторую часть умных указателей блин?
R>И я хочу привести еще один довод в пользу умных указателей. Представь, что в каком-то классе у тебя оказалось два инкапсулированных указателя. Может такое быть? И вот, ты успешно создаешь первый объект, а при создании второго летит исключение.
== авария. Дебаг, разборки, починка. Больше не летит исключение или перехвачено и обработано.
Здравствуйте, Sheridan, Вы писали:
R>>И я хочу привести еще один довод в пользу умных указателей. Представь, что в каком-то классе у тебя оказалось два инкапсулированных указателя. Может такое быть? И вот, ты успешно создаешь первый объект, а при создании второго летит исключение.
S>== авария. Дебаг, разборки, починка. Больше не летит исключение или перехвачено и обработано.
Да ясное дело, что перехвачено и обработано. Но объект ведь подвис, память утекла.
Здравствуйте, rg45, Вы писали:
R>Да ясное дело, что перехвачено и обработано. Но объект ведь подвис, память утекла.
Я же написал — такое поведение это авария, которую надо починить. Если неочевидно, то починка такой аварии по умолчанию включает в себя устранение утечек. Это значит мимо ничего не утекло.
Здравствуйте, Sheridan, Вы писали:
R>>Да ясное дело, что перехвачено и обработано. Но объект ведь подвис, память утекла. S>Я же написал — такое поведение это авария, которую надо починить. Если неочевидно, то починка такой аварии по умолчанию включает в себя устранение утечек. Это значит мимо ничего не утекло.
По-твоему, в отлаженной, правильно работающей программе исключения возникать не могут? Посмотри хотя бы на список исключений стандартной библиотеки: https://en.cppreference.com/w/cpp/error/exception — далеко не все из них связываются с ошибками в программе. Большая группа иссключений — runtime_error существет как раз для реакции на ощибки, возникающие за пределами программы. А как ты собираешься "чинить" исключения, бросаемые сторонними библиотеками?
Здравствуйте, Sheridan, Вы писали:
S>Дело было не в бобине. S>Похоже, внутри urho3d отсутствуют проверки внутри их "умных" указателей. Причём они, похоже, это монго встроили везде куда могли дотянуться.
проверка чего? того что кто-то самостоятельно удаляет объекты, которые используются?
S>Что делаю: S>
S>Казалось бы — валидный код. Ан нет, нифига подобного. У них почти любой объект — refcounted, в том числе и этот вертексбуффер. В результате валится в ReleaseRef(); внутри urho
это валидный код до тех пор пока ты не передал его куда-то.
S>Далее, интерфейсы SetVertexBuffer и SetIndexBuffer явно указывают на утечки памяти, если не удалять самостоятельно. Собственно вот поэтому и рулил сам.
они указывают на то, что Geometry этими объектами не владеет.
по хорошему, они должны быть WeakPtr.
S>И на самом деле я до сих пор сомневаюсь что там нет утечек.
если ты самостоятельно следишь за сырыми указателями, то вполне обоснованно сомневаешься.
Здравствуйте, night beast, Вы писали:
S>>Далее, интерфейсы SetVertexBuffer и SetIndexBuffer явно указывают на утечки памяти, если не удалять самостоятельно. Собственно вот поэтому и рулил сам.
NB>они указывают на то, что Geometry этими объектами не владеет. NB>по хорошему, они должны быть WeakPtr.
Совместно владеет, просто Sheridan, как обычно, делает заявления не разобравшись в сути вопроса.
PS. Было занято наблюдать оживление здесь и в КСВ на тему сырых указателей и двойного удаления в конце 2018 года. Всего 5 дней потребовалось, чтобы найти ошибку, но выводы, похоже, еще не сделаны
Здравствуйте, PM, Вы писали:
S>>>Далее, интерфейсы SetVertexBuffer и SetIndexBuffer явно указывают на утечки памяти, если не удалять самостоятельно. Собственно вот поэтому и рулил сам.
NB>>они указывают на то, что Geometry этими объектами не владеет. NB>>по хорошему, они должны быть WeakPtr.
PM>Совместно владеет, просто Sheridan, как обычно, делает заявления не разобравшись в сути вопроса.
тьфу блин. смотрел Graphics.h, там эти переменные -- сырые указатели.
PM>PS. Было занято наблюдать оживление здесь и в КСВ на тему сырых указателей и двойного удаления в конце 2018 года. Всего 5 дней потребовалось, чтобы найти ошибку, но выводы, похоже, еще не сделаны
Здравствуйте, PM, Вы писали:
PM>PS. Было занято наблюдать оживление здесь и в КСВ на тему сырых указателей и двойного удаления в конце 2018 года. Всего 5 дней потребовалось, чтобы найти ошибку, но выводы, похоже, еще не сделаны
Сходил в КСВ, развернул обсуждение и почувствовал, что силы покидают меня...
Здравствуйте, rg45, Вы писали:
R>>>Да ясное дело, что перехвачено и обработано. Но объект ведь подвис, память утекла. S>>Я же написал — такое поведение это авария, которую надо починить. Если неочевидно, то починка такой аварии по умолчанию включает в себя устранение утечек. Это значит мимо ничего не утекло.
R>По-твоему, в отлаженной, правильно работающей программе исключения возникать не могут? Посмотри хотя бы на список исключений стандартной библиотеки: https://en.cppreference.com/w/cpp/error/exception — далеко не все из них связываются с ошибками в программе. Большая группа иссключений — runtime_error существет как раз для реакции на ощибки, возникающие за пределами программы.
Ты имеешь в виду ошибки типа "память кончилась"? Ну явно их надо перехватывать не в каждой из функций программы и вообще желательно повыше и в одном месте. А уж там то можно сделать всё без утечек памяти.
R>А как ты собираешься "чинить" исключения, бросаемые сторонними библиотеками?
Практически ровно так же.
Здравствуйте, night beast, Вы писали:
S>>Дело было не в бобине. S>>Похоже, внутри urho3d отсутствуют проверки внутри их "умных" указателей. Причём они, похоже, это монго встроили везде куда могли дотянуться.
NB>проверка чего? того что кто-то самостоятельно удаляет объекты, которые используются?
Они уже не используются. Я их удаляю из сцены методами сцены. И оно потом уже, при очистке объекта крешится, так как вызывает delete на уже очищенной памяти.
S>>Казалось бы — валидный код. Ан нет, нифига подобного. У них почти любой объект — refcounted, в том числе и этот вертексбуффер. В результате валится в ReleaseRef(); внутри urho NB>это валидный код до тех пор пока ты не передал его куда-то.
Нираспарсил. Куда я этот код передавать буду? В git?
S>>Далее, интерфейсы SetVertexBuffer и SetIndexBuffer явно указывают на утечки памяти, если не удалять самостоятельно. Собственно вот поэтому и рулил сам.
NB>они указывают на то, что Geometry этими объектами не владеет.
Ты начинаешь понимать!
Это означает что раз я их использую, то значит должен владеть я, правильно? NB>по хорошему, они должны быть WeakPtr.
По хорошему он должны бы проверять на nullptr при работе с указателями, которыми владеет ктото другой.
S>>И на самом деле я до сих пор сомневаюсь что там нет утечек. NB>если ты самостоятельно следишь за сырыми указателями, то вполне обоснованно сомневаешься.
Ещё раз, следи за пальцами и читай по губам: у меня утечек нет, у меня проблем нет. Единственная возникшая проблема связана с "умными" указателями.
И я не пойму, что тут за экивоки в сторону "шеридан глупый". Ты сам соглашаешься что мой код правильный, ты сам соглашаешься что "Geometry этими объектами не владеет", сам понимаешь что раз не владеет, то значит надо самому владеть, раз используешь. В функцию что передаётся? raw ptr. Какой вывод? Управлять памятью этого объекта самостоятельно. Или нет? Какой уровень телепатии должен быть чтобы догадаться что там нужен "умный" указатель?
PM>Всего 5 дней потребовалось, чтобы найти ошибку, но выводы, похоже, еще не сделаны
6 часов. Времени особо не было посидеть в коде нормально, сидел урывками...
Выводы сделал и они подтверждают то что "умные" указатели — то ещо монго.
Смотри сам: я никогда не использую их, у меня в проектах всё ровно, ничего не течот и так далее.
Стоило только в проект попасть "умному" указателю — так сразу проблемы. НЕт, с этих пор категорически и принципиально они у меня будут только там, где без них совершенно невозможно.
PM>Шеридану спасибо!
Всем тут тоже.
Здравствуйте, Sheridan, Вы писали:
S>Ты имеешь в виду ошибки типа "память кончилась"?
Память, кончилась, юзер что-то не так сделал, да мало ли...
S>Ну явно их надо перехватывать не в каждой из функций программы и вообще желательно повыше и в одном месте. А уж там то можно сделать всё без утечек памяти.
По-моему, ты не совсем понял сценарий ошибки.
class cobject
{
public:
cobject()
: p1(new vertexbuf())
, p2(new vertexbuf()) // <--- Вот здесь летит исключение, объект p1 подвис навеки.
{
}
virtual ~cobject()
{
delete p1;
delete p2;
}
private:
vertexbuf* p1;
vertexbuf* p2;
};
Никакими перехватами, тем более "повыше" эта проблема не решается.
Здравствуйте, Sheridan, Вы писали:
S>Я хз какой доктор какие у вас болезни диагностирует.
Еще никто не добавил, что использование синглтонов в принципе дурной тон и на самом деле есть то самое "я что тут происходит, кому объект может понадобиться и когда он будет удаляццо"?
Здравствуйте, Sheridan, Вы писали:
S>>>Дело было не в бобине. S>>>Похоже, внутри urho3d отсутствуют проверки внутри их "умных" указателей. Причём они, похоже, это монго встроили везде куда могли дотянуться.
NB>>проверка чего? того что кто-то самостоятельно удаляет объекты, которые используются? S>Они уже не используются. Я их удаляю из сцены методами сцены. И оно потом уже, при очистке объекта крешится, так как вызывает delete на уже очищенной памяти.
они используются пока есть хоть один умный указатель, который им владеет.
S>>>Казалось бы — валидный код. Ан нет, нифига подобного. У них почти любой объект — refcounted, в том числе и этот вертексбуффер. В результате валится в ReleaseRef(); внутри urho NB>>это валидный код до тех пор пока ты не передал его куда-то. S>Нираспарсил. Куда я этот код передавать буду? В git?
не код а сырой указатель.
S>>>Далее, интерфейсы SetVertexBuffer и SetIndexBuffer явно указывают на утечки памяти, если не удалять самостоятельно. Собственно вот поэтому и рулил сам.
NB>>они указывают на то, что Geometry этими объектами не владеет. S>Ты начинаешь понимать!
S>Это означает что раз я их использую, то значит должен владеть я, правильно?
это значит, что если ты владеешь указателем, то должен явно выразить свое желание, обернув его в шаред.
NB>>по хорошему, они должны быть WeakPtr. S>По хорошему он должны бы проверять на nullptr при работе с указателями, которыми владеет ктото другой.
проверять на nullptr что?
S>>>И на самом деле я до сих пор сомневаюсь что там нет утечек. NB>>если ты самостоятельно следишь за сырыми указателями, то вполне обоснованно сомневаешься. S>Ещё раз, следи за пальцами и читай по губам: у меня утечек нет, у меня проблем нет. Единственная возникшая проблема связана с "умными" указателями.
читай по губам: у тебя проблемы с пониманием того, как работают умные указатели с интрузивным подсчетом ссылок. других проблем не вижу.
S>И я не пойму, что тут за экивоки в сторону "шеридан глупый". Ты сам соглашаешься что мой код правильный, ты сам соглашаешься что "Geometry этими объектами не владеет", сам понимаешь что раз не владеет, то значит надо самому владеть, раз используешь.
как выяснилось, владеет.
S>В функцию что передаётся? raw ptr. Какой вывод? Управлять памятью этого объекта самостоятельно. Или нет? Какой уровень телепатии должен быть чтобы догадаться что там нужен "умный" указатель?
в функцию передается raw ptr, скорее всего, чтобы избежать лишних инкрементов/декрементов на ровном месте.
телепатии не нужно, просто используй объекты так, как планировали их разработчики, и все будет нормально.
Здравствуйте, rg45, Вы писали:
S>>Ты имеешь в виду ошибки типа "память кончилась"? R>Память, кончилась, юзер что-то не так сделал, да мало ли...
Мало ли, да. Только давай мух отдельно, котлеты отдельно. Если юзер чтото не так сделал, то это одно, а если ресурсы закончились, то редко когда можно чего сделать. Ну, разве что попробовать освободить память, если есть какие кеши...
S>>Ну явно их надо перехватывать не в каждой из функций программы и вообще желательно повыше и в одном месте. А уж там то можно сделать всё без утечек памяти. R>По-моему, ты не совсем понял сценарий ошибки. R>Никакими перехватами, тем более "повыше" эта проблема не решается.
Почему исключение нельзя перехватить в конструкторе? Почему ты придумываешь мне редкие аварии?
Здравствуйте, landerhigh, Вы писали:
L>Еще никто не добавил, что использование синглтонов в принципе дурной тон и на самом деле есть то самое "я что тут происходит, кому объект может понадобиться и когда он будет удаляццо"?
Нет. У меня синглтон как раз по делу. Репозиторий объектов, которые в приложении нужны в единственном экземпляре. Причом глобально приложению.
Можно конечно было и через наследование всеми и каждым некоего CObject сделать с нужными полями, но такое по моему совершенный зашквар.
Здравствуйте, Sheridan, Вы писали:
S>Здравствуйте, night beast, Вы писали:
NB>>тьфу блин. смотрел Graphics.h, там эти переменные -- сырые указатели. S>Но при этом S>Хотя тут же рядом
и?
S>Что тут можно решить кроме "а, ну если бы им нужен был "умный", то они бы его и попросили, а тут просят raw. Ну будет тебе raw."
объясни мне простую вещь, у них в примерах/документации тоже везде ручные delete используются?
class cobject
{
public:
cobject()
: p1(new vertexbuf())
, p2(new vertexbuf()) // <--- Вот здесь летит исключение, объект p1 подвис навеки.
{
}
virtual ~cobject()
{
delete p1;
delete p2;
}
private:
vertexbuf* p1;
vertexbuf* p2;
};
S>Почему исключение нельзя перехватить в конструкторе? Почему ты придумываешь мне редкие аварии?
Можно. Но!
1. Что ты будешь с этим исключением делать? Как ты определишь, какой из объектов кинул исключение? Они ведь неразличимы. Или ты будешь инициализацию каждого мембера в отдельности обраблять в try- catch?
2. Эту проблему нужно будет решать в КАЖДОМ классе, содережащем более одного указателя. Представь, во что превратится твой код и какое количество ошибок будет плодиться в этом аду.
3. Откуда у тебя уверенность, что эта ситуация редкая? А даже если и редкая, то что — можно игнорировать что ли?
И главное: зачем создавать сложности, когда все эти "но" разрешаются предельно просто:
class cobject
{
public:
cobject()
: p1(new vertexbuf())
, p2(new vertexbuf()) // <--- Вот здесь летит исключение - а нам насрать!
{
}
virtual ~cobject(){}
private:
shared_ptr<vertexbuf> p1;
shared_ptr<vertexbuf> p2;
};
Здравствуйте, night beast, Вы писали:
NB>>>проверка чего? того что кто-то самостоятельно удаляет объекты, которые используются? S>>Они уже не используются. Я их удаляю из сцены методами сцены. И оно потом уже, при очистке объекта крешится, так как вызывает delete на уже очищенной памяти. NB>они используются пока есть хоть один умный указатель, который им владеет.
Они уже не используются. Всё. Нода из сцены удаляется. Удаление как раз в момент между кадрами, когда эти данные никому не нужны.
Владеть указателем может только "умная" обёртка?
S>>>>Казалось бы — валидный код. Ан нет, нифига подобного. У них почти любой объект — refcounted, в том числе и этот вертексбуффер. В результате валится в ReleaseRef(); внутри urho NB>>>это валидный код до тех пор пока ты не передал его куда-то. S>>Нираспарсил. Куда я этот код передавать буду? В git? NB>не код а сырой указатель.
Я владею этим указателем, управляю его жизнью. Почему я не могу его передать кому то еще на время — непонятно.
Почему это нельзя только мне, а можно в urho тоже неясно.
S>>>>Далее, интерфейсы SetVertexBuffer и SetIndexBuffer явно указывают на утечки памяти, если не удалять самостоятельно. Собственно вот поэтому и рулил сам. NB>>>они указывают на то, что Geometry этими объектами не владеет. S>>Это означает что раз я их использую, то значит должен владеть я NB>это значит, что если ты владеешь указателем, то должен явно выразить свое желание, обернув его в шаред.
Нет. Владеть указателем могут не только "умные" обёртки, тебя обманули.
NB>>>по хорошему, они должны быть WeakPtr. S>>По хорошему он должны бы проверять на nullptr при работе с указателями, которыми владеет ктото другой. NB>проверять на nullptr что?
Указатель, который к ним приходит, которым владеет ктото извне. Ваш кэп. не благодарите.
S>>>>И на самом деле я до сих пор сомневаюсь что там нет утечек. NB>>>если ты самостоятельно следишь за сырыми указателями, то вполне обоснованно сомневаешься. S>>Ещё раз, следи за пальцами и читай по губам: у меня утечек нет, у меня проблем нет. Единственная возникшая проблема связана с "умными" указателями. NB>читай по губам: у тебя проблемы с пониманием того, как работают умные указатели с интрузивным подсчетом ссылок. других проблем не вижу.
Я лично вижу что работает это совершенно рукожопно. Баги на ровном месте.
S>>И я не пойму, что тут за экивоки в сторону "шеридан глупый". Ты сам соглашаешься что мой код правильный, ты сам соглашаешься что "Geometry этими объектами не владеет", сам понимаешь что раз не владеет, то значит надо самому владеть, раз используешь. NB>как выяснилось, владеет.
Нихрена не владеет. Эти данные ктото другой в туда поставлять должен, а геометри просто хранит указатель на них.
S>>В функцию что передаётся? raw ptr. Какой вывод? Управлять памятью этого объекта самостоятельно. Или нет? Какой уровень телепатии должен быть чтобы догадаться что там нужен "умный" указатель? NB>в функцию передается raw ptr, скорее всего, чтобы избежать лишних инкрементов/декрементов на ровном месте.
Во, начались гадания. Скорее всего...
Вы уж определитесь со своими "умными" указателями. Они должны быть либо умными, и тогда никаких get raw ptr методов, либо не нужны.
NB>телепатии не нужно, просто используй объекты так, как планировали их разработчики, и все будет нормально.
Глядя на их код хер поймош чего они там планировали.
Здравствуйте, night beast, Вы писали:
S>>Что тут можно решить кроме "а, ну если бы им нужен был "умный", то они бы его и попросили, а тут просят raw. Ну будет тебе raw." NB>объясни мне простую вещь, у них в примерах/документации тоже везде ручные delete используются?
У них там везде явные SharedPtr, причом на ровных местах даже там где не нужны.
Но в метод они явно и недвусмысленно ожидают прилёта raw указателя. Значит этим указателем должен владеть я, выделяя ему память и удаляя потом.
Здравствуйте, rg45, Вы писали:
R>1. Что ты будешь с этим исключением делать? Как ты определишь, какой из объектов кинул исключение? Они ведь неразличимы.
Значит перепишу так, чтобы были различимы, раз уж именно тут надо перехватить и именно в таких условиях.
R>2. Эту проблему нужно будет решать в КАЖДОМ классе, содережащем более одного указателя. Представь, во что превратится твой код и какое количество ошибок будет плодиться в этом аду.
Если ВНЕЗАПНО чтото начинает пригождаться в ЛЮБОМ классе, то явно нужно сделать шаг выше. Или ниже. Чтобы свернуть веер решений до одного.
R>3. Откуда у тебя уверенность, что это "авария" и что она редкая. А даже если и редкая, то что — можно игнорировать что ли?
Оттуда что у меня всё что делает не так юзер — перехватывается совершенно в другом месте. А если в отлаженном коде прилетел exception, то варианта ровно два:
1. Это явная авария, причом такая что скорее всего надо извиниться перед юзером и здохнуть, отправив отчот.
2. Проект еще у разрабов и они как раз чегото пилят рядом.
R>И главное: зачем создавать сложности, когда все эти "но" разрешаются предельно просто:
Потому что "умные" указатели — говённое говно, в чом я лишний раз только что убедился.
Здравствуйте, Sheridan, Вы писали:
S>Владеть указателем может только "умная" обёртка?
начинаешь о чем-то подозревать?
NB>>не код а сырой указатель. S>Я владею этим указателем, управляю его жизнью. Почему я не могу его передать кому то еще на время — непонятно. S> Почему это нельзя только мне, а можно в urho тоже неясно.
может быть потому что эти классы разрабатывали они, а не ты?
NB>>это значит, что если ты владеешь указателем, то должен явно выразить свое желание, обернув его в шаред. S>Нет. Владеть указателем могут не только "умные" обёртки, тебя обманули.
ну нет, так нет. успехов в дальнейших поисках "непонятных крашей".
NB>>>>по хорошему, они должны быть WeakPtr. S>>>По хорошему он должны бы проверять на nullptr при работе с указателями, которыми владеет ктото другой. NB>>проверять на nullptr что? S>Указатель, который к ним приходит, которым владеет ктото извне. Ваш кэп. не благодарите.
скажи мне, кэп, откуда они узнают что ты у себя где-то обнулил этот указатель?
S>>>И я не пойму, что тут за экивоки в сторону "шеридан глупый". Ты сам соглашаешься что мой код правильный, ты сам соглашаешься что "Geometry этими объектами не владеет", сам понимаешь что раз не владеет, то значит надо самому владеть, раз используешь. NB>>как выяснилось, владеет. S>Нихрена не владеет. Эти данные ктото другой в туда поставлять должен, а геометри просто хранит указатель на них.
шаредптр предполагает совместное владение. если там использован шаредптр, то значит владеет, как бы тебе не хотелось обратного.
S>Во, начались гадания. Скорее всего... S>Вы уж определитесь со своими "умными" указателями. Они должны быть либо умными, и тогда никаких get raw ptr методов, либо не нужны.
объясняю.
если есть гарантии, что пока используется raw ptr, есть живые шареды, то использовать их можно. не благодари.
Здравствуйте, Sheridan, Вы писали:
S>>>Что тут можно решить кроме "а, ну если бы им нужен был "умный", то они бы его и попросили, а тут просят raw. Ну будет тебе raw." NB>>объясни мне простую вещь, у них в примерах/документации тоже везде ручные delete используются? S>У них там везде явные SharedPtr, причом на ровных местах даже там где не нужны. S>Но в метод они явно и недвусмысленно ожидают прилёта raw указателя. Значит этим указателем должен владеть я, выделяя ему память и удаляя потом.
то есть в документации показано, как правильно использовать их либу, но ты решил что знаешь лучше, как надо, и теперь жалуешься что что-то не работает?
Здравствуйте, night beast, Вы писали:
S>>Владеть указателем может только "умная" обёртка? NB>начинаешь о чем-то подозревать?
Я не подозреваю, я знаю.
NB>>>не код а сырой указатель. S>>Я владею этим указателем, управляю его жизнью. Почему я не могу его передать кому то еще на время — непонятно. S>> Почему это нельзя только мне, а можно в urho тоже неясно. NB>может быть потому что эти классы разрабатывали они, а не ты?
Софистика.
NB>>>это значит, что если ты владеешь указателем, то должен явно выразить свое желание, обернув его в шаред. S>>Нет. Владеть указателем могут не только "умные" обёртки, тебя обманули. NB>ну нет, так нет. успехов в дальнейших поисках "непонятных крашей".
Когда я не хочу управлять памятью, я беру перл, питон, js и так далее.
NB>>>>>по хорошему, они должны быть WeakPtr. S>>>>По хорошему он должны бы проверять на nullptr при работе с указателями, которыми владеет ктото другой. NB>>>проверять на nullptr что? S>>Указатель, который к ним приходит, которым владеет ктото извне. Ваш кэп. не благодарите. NB>скажи мне, кэп, откуда они узнают что ты у себя где-то обнулил этот указатель?
Проверить на nullptr например?
S>>>>И я не пойму, что тут за экивоки в сторону "шеридан глупый". Ты сам соглашаешься что мой код правильный, ты сам соглашаешься что "Geometry этими объектами не владеет", сам понимаешь что раз не владеет, то значит надо самому владеть, раз используешь. NB>>>как выяснилось, владеет. S>>Нихрена не владеет. Эти данные ктото другой в туда поставлять должен, а геометри просто хранит указатель на них. NB>шаредптр предполагает совместное владение. если там использован шаредптр, то значит владеет, как бы тебе не хотелось обратного.
Моя ошибка в том что я не дочитал сорцы до конца.
S>>Во, начались гадания. Скорее всего... S>>Вы уж определитесь со своими "умными" указателями. Они должны быть либо умными, и тогда никаких get raw ptr методов, либо не нужны. NB>объясняю. NB>если есть гарантии, что пока используется raw ptr, есть живые шареды, то использовать их можно. не благодари.
Я и так гарантировал что пока данные нужны — они есть. И если бы не "умные" указатели — это бы работало.
Здравствуйте, night beast, Вы писали:
S>>>>Что тут можно решить кроме "а, ну если бы им нужен был "умный", то они бы его и попросили, а тут просят raw. Ну будет тебе raw." NB>>>объясни мне простую вещь, у них в примерах/документации тоже везде ручные delete используются? S>>У них там везде явные SharedPtr, причом на ровных местах даже там где не нужны. S>>Но в метод они явно и недвусмысленно ожидают прилёта raw указателя. Значит этим указателем должен владеть я, выделяя ему память и удаляя потом. NB>то есть в документации показано, как правильно использовать их либу, но ты решил что знаешь лучше, как надо, и теперь жалуешься что что-то не работает?
Все примеры в документации не предполагают изменение сцены. Как создали сцену, так её и используют. Ну, иногда добавляют объекты. Но не удаляют. А мне надо еще и удалять.
Здравствуйте, Sheridan, Вы писали:
NB>>>>>>по хорошему, они должны быть WeakPtr. S>>>>>По хорошему он должны бы проверять на nullptr при работе с указателями, которыми владеет ктото другой. NB>>>>проверять на nullptr что? S>>>Указатель, который к ним приходит, которым владеет ктото извне. Ваш кэп. не благодарите. NB>>скажи мне, кэп, откуда они узнают что ты у себя где-то обнулил этот указатель? S>Проверить на nullptr например?
Здравствуйте, night beast, Вы писали:
NB>>>скажи мне, кэп, откуда они узнают что ты у себя где-то обнулил этот указатель? S>>Проверить на nullptr например?
NB>давай ты попробуешь изобразить это в коде?
Здравствуйте, Sheridan, Вы писали:
NB>>>>скажи мне, кэп, откуда они узнают что ты у себя где-то обнулил этот указатель? S>>>Проверить на nullptr например?
NB>>давай ты попробуешь изобразить это в коде? S>
Здравствуйте, Sheridan, Вы писали:
S>В функцию что передаётся? raw ptr. Какой вывод? Управлять памятью этого объекта самостоятельно. Или нет? Какой уровень телепатии должен быть чтобы догадаться что там нужен "умный" указатель?
У них в документации есть интересная заметка.
Raw pointers are used whenever possible in the classes' public API. This simplifies exposing functions & classes to script, and is relatively safe, because SharedPtr & WeakPtr use intrusive reference counting.
Из этого прямо не следует, что для управления памятью, выделенной под указатели везде умные указатели используются, но это повод подробнее посмотреть документацию и примеры.
Здравствуйте, night beast, Вы писали:
NB>то есть в документации показано, как правильно использовать их либу, но ты решил что знаешь лучше, как надо, и теперь жалуешься что что-то не работает?
Это плохой подход к разработке библиотеки. Если специально не оговорено, что при каких-то условиях не будет работать, то должно работать. Если же работает только по определённым сценариям, то значит авторы слишком много о себе думают.
Здравствуйте, night beast, Вы писали:
S>>В функцию что передаётся? raw ptr. Какой вывод? Управлять памятью этого объекта самостоятельно. Или нет? Какой уровень телепатии должен быть чтобы догадаться что там нужен "умный" указатель? NB>в функцию передается raw ptr, скорее всего, чтобы избежать лишних инкрементов/декрементов на ровном месте.
Хотите избежать лишних инкрементов/декрементов на ровном месте? Передавайте ссылку!
Это явная ошибка дизайна:
class Geometry
{
...
Vector<SharedPtr<VertexBuffer> > vertexBuffers_;
...
};
bool Geometry::SetVertexBuffer(unsigned index, VertexBuffer* buffer)
{
if (index >= vertexBuffers_.Size())
{
URHO3D_LOGERROR("Stream index out of bounds");
return false;
}
vertexBuffers_[index] = buffer;
return true;
}
Должно быть:
bool Geometry::SetVertexBuffer(unsigned index, const SharedPtr<VertexBuffer>& buffer)
{
if (index >= vertexBuffers_.Size())
{
URHO3D_LOGERROR("Stream index out of bounds");
return false;
}
vertexBuffers_[index] = buffer;
return true;
}
Здравствуйте, B0FEE664, Вы писали:
S>>>В функцию что передаётся? raw ptr. Какой вывод? Управлять памятью этого объекта самостоятельно. Или нет? Какой уровень телепатии должен быть чтобы догадаться что там нужен "умный" указатель? NB>>в функцию передается raw ptr, скорее всего, чтобы избежать лишних инкрементов/декрементов на ровном месте. BFE> BFE>Хотите избежать лишних инкрементов/декрементов на ровном месте? Передавайте ссылку! BFE>Это явная ошибка дизайна:
Здравствуйте, Sheridan, Вы писали:
L>>Еще никто не добавил, что использование синглтонов в принципе дурной тон и на самом деле есть то самое "я что тут происходит, кому объект может понадобиться и когда он будет удаляццо"? S>Нет. У меня синглтон как раз по делу.
Здравствуйте, night beast, Вы писали:
BFE>>Это явная ошибка дизайна: NB>чуть выше уже написали обоснование этому решению.
Это не обоснование, а рассказ от любителей разбрасывать грабли о том, что где-то в их коде лежат грабли. Авторам ничего не мешает сгенерить отдельный API для своих скриптов (чем бы эти скрипты не были).
Здравствуйте, night beast, Вы писали:
NB>так, да?
Ты в этой ветке уже кажется третий кто ему пытается таким образом объяснить , и у него похоже проблема с пониманием что такое указатель.
Sheridan при delete ptr; и ptr = nullptr; — обнуляется только переменая ptr, никакие другие указатели на туже память не обнуляются, указатель это переменая, она занимает память, а то о чём ты мечтаешь будет указатель на указатель, но мой тебе совет, не иди по этому пути, помню у меня был друг у которого доходило до ****ptr, этож застрелиться.
Здравствуйте, Igore, Вы писали:
I>Sheridan при delete ptr; и ptr = nullptr; — обнуляется только переменая ptr, никакие другие указатели на туже память не обнуляются, указатель это переменая, она занимает память, а то о чём ты мечтаешь будет указатель на указатель, но мой тебе совет, не иди по этому пути, помню у меня был друг у которого доходило до ****ptr, этож застрелиться.
Ой да ладно! Застрелился он...
Smart указатели на то и смарт, что могут всё:
Здравствуйте, B0FEE664, Вы писали:
BFE>Здравствуйте, Igore, Вы писали:
I>>Sheridan при delete ptr; и ptr = nullptr; — обнуляется только переменая ptr, никакие другие указатели на туже память не обнуляются, указатель это переменая, она занимает память, а то о чём ты мечтаешь будет указатель на указатель, но мой тебе совет, не иди по этому пути, помню у меня был друг у которого доходило до ****ptr, этож застрелиться.
BFE>Ой да ладно! Застрелился он... BFE>Smart указатели на то и смарт, что могут всё:
Не не не, ты не понял, голые указатели с четвертым уровнем косвености, никаких умных указателей void**** m_someDataPtr;
Здравствуйте, Sheridan, Вы писали:
R>>1. Что ты будешь с этим исключением делать? Как ты определишь, какой из объектов кинул исключение? Они ведь неразличимы. S>Значит перепишу так, чтобы были различимы, раз уж именно тут надо перехватить и именно в таких условиях.
Это предложение говорит мне о том, что тебе очень мало приходилось работать с чужим кодом. А я видел код, сделанный как раз "чтобы были различимы". Причем на гораздо менее злобной Java.
Ты подумай: а вдруг с этим твоим кодом начнет работать маньяк, который знает твой домашний адрес?
Здравствуйте, AleksandrN, Вы писали:
S>>В функцию что передаётся? raw ptr. Какой вывод? Управлять памятью этого объекта самостоятельно. Или нет? Какой уровень телепатии должен быть чтобы догадаться что там нужен "умный" указатель?
AN>У них в документации есть интересная заметка. AN>
AN>Raw pointers are used whenever possible in the classes' public API. This simplifies exposing functions & classes to script, and is relatively safe, because SharedPtr & WeakPtr use intrusive reference counting.
AN>Из этого прямо не следует, что для управления памятью, выделенной под указатели везде умные указатели используются, но это повод подробнее посмотреть документацию и примеры.
When making your own work functions or threads, observe that the following things are unsafe and will result in undefined behavior and crashes, if done outside the main thread:
Modifying scene or UI content
Modifying GPU resources
Executing script functions Pointing SharedPtr's or WeakPtr's to the same RefCounted object from multiple threads simultaneously
Терзают меня смутные сомнения, что такой mirror_ptr может на что-нибудь полезное сгодиться. И долго хранить в куче ссылку на указатель (да и вообще на что либо) я бы поостерёгся.
Здравствуйте, ViTech, Вы писали:
VT>Терзают меня смутные сомнения, что такой mirror_ptr может на что-нибудь полезное сгодиться. И долго хранить в куче ссылку на указатель (да и вообще на что либо) я бы поостерёгся.
Ни в коем случае не используйте приведённый код в домашних условиях и уж точно не используйте в продакшен. Код приведён исключительно в образовательных целях и должен рассматриваться исключительно как этюд.
Здравствуйте, rg45, Вы писали:
S>>Да тут тред не про это. Тут тред про "шеридан дурак" R>Тред создал ты, если ты уже забыл. "Помогите, мои идеальные программы крешатся".
У меня ничего не крешится. Крешится из за "умных" указателей в урхо, криво прикрученных везде подряд.
Здравствуйте, Sheridan, Вы писали:
S>Здравствуйте, rg45, Вы писали:
S>>>Да тут тред не про это. Тут тред про "шеридан дурак" R>>Тред создал ты, если ты уже забыл. "Помогите, мои идеальные программы крешатся". S>У меня ничего не крешится. Крешится из за "умных" указателей в урхо, криво прикрученных везде подряд.
"Сказ про то, как Шеридан в чужой монастырь со своим уставом ходил, или Туда и обратно".
Здравствуйте, Sheridan, Вы писали:
S>Дело было не в бобине. S>Похоже, внутри urho3d отсутствуют проверки внутри их "умных" указателей. Причём они, похоже, это монго встроили везде куда могли дотянуться. S>Что делаю: S>
---
UPD. Я частично просмотрел ответы в этой подветке.
Но не увидел объяснения и простого совета для начинающего программировать на плюсах — первым делом запрещай у класса конструктор и оператор копирования.
Я обычно пишу так (копирую из первого попавшегося файла):
class IBP_OLEDB_Props2__Handler__PrepareSetValue__Prop__ext_props
:public IBP_OLEDB_Props2__Handler__PrepareSetValue
{
private:
typedef IBP_OLEDB_Props2__Handler__PrepareSetValue__Prop__ext_props self_type;
IBP_OLEDB_Props2__Handler__PrepareSetValue__Prop__ext_props(const self_type&); //без реализации
self_type& operator = (const self_type&); //без реализации
Современные плюсы позволяют еще писать еще более конкретно:
Компилятор сгенерирует их самостоятельно и это будет бинарное копирование объекта, которое приведет с двум (и более) объектам, указывающие на одну и туже память buf.
cobject x1;
cobject x2(x1); //x2 указывает на тот же buf что и x1
Соответственно она будет дважды удаляться.
Если вызовется сгенерированный оператор копирования, то у тебя еще и память начнет течь, потому что будет перезатираться указатель.
cobject x1;
cobject x2;
x1=x2; //x1 потерял указатель на память, которую он выделил в конструкторе
Наверное это можно было отследить поставив точку прерывания в деструкторе.
---
Если бы ты эти две вещи сразу запретил бы, то скорее всего не смог бы откомпилировать программу.
И пришлось бы эти копирующие конструкции определять.
---
Тут по-моему советовали засунуть buf в смарт-указатель. Это решило бы проблему с освобождением памяти buf.
Но скорее всего создало бы другую — если предполагается, что cobject единственный владелец у памяти, на которую указывает buf.
---
Надеюсь я правильно объяснил ошибку в твоем классе и дал корректный совет
-- Пользователи не приняли программу. Всех пришлось уничтожить. --
Здравствуйте, reversecode, Вы писали:
R>зачем люди занимаются то в чем они не разбираются или разбираются плохо ?
Ну захотелось админу попрограммировать, ты чем против?
[In theory there is no difference between theory and practice. In
practice there is.]
[Даю очевидные ответы на риторические вопросы]
Здравствуйте, wander, Вы писали:
W>Интрузивный указатель же. Старая и известная всем идиома.
Нарушать инкапсуляцию — бредовая идея. Объекты обязаны быть самодостаточными и явно требовать нужное им для жизни при инициализации.
Здравствуйте, Sheridan, Вы писали:
S>Нарушать инкапсуляцию — бредовая идея. Объекты обязаны быть самодостаточными и явно требовать нужное им для жизни при инициализации.
Она не нарушается. Работа со счетчиком ссылок — это часть контракта класса.
Смарт-пойнтер — использует этот контракт.
Примеры использования можно встретить в COM, CORBA, boost::intrusive, Ipopt, в некоторых игровых движках и много где еще.
Вы слишком самоуверенно судите о вещах, о которых узнали не больше недели назад.
А убеждение в собственной непогрешимости чести вам тоже не делает.
Хотя и понятно, что при наличии подобного убеждения, мои слова просто дадут вам еще +1 человека, которого вы сочтете идиотом.
Здравствуйте, wander, Вы писали:
S>>Нарушать инкапсуляцию — бредовая идея. Объекты обязаны быть самодостаточными и явно требовать нужное им для жизни при инициализации.
W>Она не нарушается. Работа со счетчиком ссылок — это часть контракта класса. W>Смарт-пойнтер — использует этот контракт.
Говённые значит приёмы написания кода, которые нарушают логику. Контракты какието... Как эти контракты описываются в коде? Специфический синтаксис? Или просто "мы тут поговорили и решили!" (кто бы ни был этими "мы")?
W>Примеры использования можно встретить в COM, CORBA, boost::intrusive, Ipopt, в некоторых игровых движках и много где еще.
Там тоже нарушается инкапсуляция? Тоже один объект ВНЕЗАПНО думает что его используется совместно с другим, при этом "другой" никак не инициализируя или хотя бы проверяется жив ли?
W>Вы слишком самоуверенно судите о вещах, о которых узнали не больше недели назад.
Если я вижу говно — я говорю что это говно. Не приемлю фанатичную толерантность.
W>А убеждение в собственной непогрешимости чести вам тоже не делает.
Откуда это? Я гдето писал что непогрешим и что я истина в последней инстанции? о0
W>Хотя и понятно, что при наличии подобного убеждения, мои слова просто дадут вам еще +1 человека, которого вы сочтете идиотом.
Ещо одного человека, который привык к подобному поведению объектов. Но почему то считает что подобное поведение — хорошо.
Здравствуйте, Sheridan, Вы писали:
W>>Она не нарушается. Работа со счетчиком ссылок — это часть контракта класса. W>>Смарт-пойнтер — использует этот контракт. S>Говённые значит приёмы написания кода, которые нарушают логику. Контракты какието...
Вот о чем я и говорю. Безапелляционная, или, как вы говорите — фанатичная, уверенность в собственной правоте.
Я-то тут не свое личное мнение озвучиваю, а принятую практику на определенном классе задач.
Опять же, никто не говорит, что такое нужно везде и всегда, но и то, что это всегда безальтернативно "говно" — может говорить только очень самоуверенный человек.
Хотите разобраться — почитайте мотивацию для применения интрузивных объектов, благо, сейчас информация всем доступна через поиск.
S>Как эти контракты описываются в коде? Специфический синтаксис? Или просто "мы тут поговорили и решили!" (кто бы ни был этими "мы")?
У объекта есть функции: "увеличить счетчик" и "освободить себя", функция освобождения уменьшает счетчик и вызывает деаллокацию при его нуле.
Вы нарушили контракт объекта, начав владеть им без увеличения счетчика, за что и получили ошибку.
Понимаю, идиома может показаться сложной для неопытного* человека или неочевидной, но у нее есть области применения, обоснованные и признанные сообществом.
Критикуя ее на базе вашего недельного опыта — вы ставите под сомнение весь опыт сообщества и это выглядит крайне самонадеяно.
(И, пожалуйста, не надо возражать мне фразой про "миллионы мух", если кто-то сравнивает квалифицированных инженеров с мухами, то я даже не знаю на какой орбите его самооценка находится — думаю, где-то на уровне библейского Икара, который, все мы помним как закончил).
W>>Примеры использования можно встретить в COM, CORBA, boost::intrusive, Ipopt, в некоторых игровых движках и много где еще. S>Там тоже нарушается инкапсуляция? Тоже один объект ВНЕЗАПНО думает что его используется совместно с другим, при этом "другой" никак не инициализируя или хотя бы проверяется жив ли?
Если объект предполагает совместное использование, то это не может являться нарушением его инкапсуляции.
W>>А убеждение в собственной непогрешимости чести вам тоже не делает. S>Откуда это? Я гдето писал что непогрешим и что я истина в последней инстанции? о0
Конечно. Ошибку сделали вы, а виноваты вокруг все остальные
W>>Хотя и понятно, что при наличии подобного убеждения, мои слова просто дадут вам еще +1 человека, которого вы сочтете идиотом. S>Ещо одного человека, который привык к подобному поведению объектов. Но почему то считает что подобное поведение — хорошо.
Не бывает такого "хорошо" или "плохо" — это же не религия. Бывает "уместно", "обосновано" или наоборот.
Естественно есть множество ситуаций, когда подобный объект будет не уместен.
Но то, что он был неуместен именно в данной ситуации еще нужно доказать, и явно не утверждениями "все это бред и глупость".
И даже если вы это докажете, это все равно не будет означать, что идиома "бредовая", а лишь только то, что ее в данной ситуации неверно
или небезопасно применили.
R>Правильно, потому, что у них любой класс, в том числе и этот вертексбуффер, заточен на использование с их умным указателем: Urho3D::SharedPtr. И выглядеть это, по их задумке, должно бы примерно так:
Непонятно только почему они оставили деструктор у RefCounted публичным. Иначе может и Шеридан не споткнулся бы об ручное разрушение объекта.
SD>Непонятно только почему они оставили деструктор у RefCounted публичным. Иначе может и Шеридан не споткнулся бы об ручное разрушение объекта.
Как я догадываюсь, они допускали, все-таки, кастомное владение объектами и прямой доступ к управлению счетчиками ссылок. Включая возможность создания объектов на стеке и написание собственных умных указателей. По соображениям оптимизации и предоставлению пользователю большей гибкости. Но возможно и зря они это делали. Пользователь — это такой юзверь, который прострелит себе ногу и скажет, что виноват тот, кто сделал ружье.
SD>Хотя...))
Здравствуйте, Sheridan, Вы писали:
W>>Интрузивный указатель же. Старая и известная всем идиома. S>Нарушать инкапсуляцию — бредовая идея. Объекты обязаны быть самодостаточными и явно требовать нужное им для жизни при инициализации.
Есть такое выражение — цивилизация потребления. Так вот, нужно создать потребителя данных создаваемого по запросу пользователя, но зависящего от третьей стороны. И создателя (отправителя) данных, который не владеет целью и которая, опять таки, не имеет прямой связи с временем жизни сервера (принимаемой стороны).
Наверное, как аналогию — можно привести TCP соединение, когда наши команды могут завершаться неудачей. Однако в случае прямой посылки сообщений (вызовов методов), нам нужно или владеть объектами или иметь механизм овладевать целью на время, для того, что отправлять те самые сообщения.
Даже, если, предположить, что время жизни можно сделать заранее известным (что, как правило, не так) — твой подход лишает систему типов (и нас программистов) об этом самом факте, кто там и чем владеет или не владеет.
По сути, я так понял, ты говоришь, что достаточно указателей. И формально, это правда — но лишь для исполнительной машины. Она кстати и указатель от натурального целого не отличает, не находишь это странным? Можно и указатель стереть из стстемы типов и это будет работать.
Но, т.к. мы люди — мы не можем знать о комментарии в начале файла, в конце файла или где-то между, не будем из все читать, видя просто указатель. Поэтому такого рода информация, всегда должна быть in-place, что смарт-поинтеры и дают.
Ну, это так, можно не отвечать, отвечать не буду все равно (не дотянусь).