Здравствуйте, 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 переделывать.