Моя устаревшая кодовая база C ++ терпит неудачу в многопоточном сценарии выполнения, когда два потока одновременно пытаются выделить память для вектора STL. Трассировка стека двух потоков приведена ниже.
----------------- lwp# 4 / thread# 4 --------------------
00136e10 allocate__t24__default_alloc_template2b0i0Ui (4, 4, 0, 0, 0, 0) + a4
0015ee80 allocate__t12simple_alloc2ZP12ReconInitRecZt24__default_alloc_template2b0i0Ui (1, 0, 0, 0
, 0, 0) + 20
0015da24 _M_allocate__t18_Vector_alloc_base3ZP12ReconInitRecZt9allocator1ZP12ReconInitRecb1Ui (86f
204, 1, 0, 0, 0, 0) + 10
0014f438 _M_insert_aux__t6vector2ZP12ReconInitRecZt9allocator1ZP12ReconInitRecPP12ReconInitRecRCP1
2ReconInitRec (86f204, 0, fbe7fd04, 0, 0, 0) + cc
0015f0a8 push_back__t6vector2ZP12ReconInitRecZt9allocator1ZP12ReconInitRecRCP12ReconInitRec (86f20
4, fbe7fd04, 0, 0, 0, 0) + 5c
0015dbc0 push_back__t26ReconListOfRecFromMMapFile1ZP12ReconInitRecRCP12ReconInitRec (86f1f0, fbe7f
d04, 0, 0, fc551200, ff120400) + 28
0017ca48 preprocess__8ReconCmpRCt26ReconListOfRecFromMMapFile1ZP12ReconInitRecb (86f160, 975100, 0
, b4, b4, 1) + 268
<<other stacktrace details truncated>>
. . . .
ff1494f0 _lwp_start (0, 0, 0, 0, 0, 0)
----------------- lwp# 5 / thread# 5 --------------------
ff14d1e4 _lwp_kill (6, 0, ff1b5010, ff12c928, ffffffff, 6) + 8
ff0c1bac abort (1f2b24, 1, 264ae4, ee930, ff1b34d8, 0) + 110
001f2ca8 corehandler__7CdrSigsi (a, 0, fbaff4a8, 1, fedb2c40, cb4) + 184
ff14961c __sighndlr (a, 0, fbaff4a8, 1f2b24, 0, 1) + c
ff13dce8 call_user_handler (a, 0, 4, 0, fc551a00, fbaff4a8) + 3b8
ff13ded0 sigacthandler (a, 0, fbaff4a8, 0, 0, 0) + 60
--- called from signal handler with signal 10 (SIGBUS) ---
00136e10 allocate__t24__default_alloc_template2b0i0Ui (8, 8, fbaffa38, 2d, 0, 0) + a4
00126300 allocate__t12simple_alloc2Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc
_template2b0i0Zt24__default_alloc_template2b0i0Ui (2, 4, ffffffff, fbaffa38, 2d, 80808080) + 20
00126338 _M_allocate__t18_Vector_alloc_base3Zt12basic_string3ZcZt18string_char_traits1ZcZt24__defa
ult_alloc_template2b0i0Zt9allocator1Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc
_template2b0i0b1Ui (86f2a0, 2, 2d, fbaffa65, fbaffa65, 1) + 10
00133768 _M_insert_aux__t6vector2Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_t
emplate2b0i0Zt9allocator1Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b
0i0Pt12basic_string3ZcZt18string_char_traits1ZcZt24__defa (86f2a0, 8730b4, fbaffa20, fcbf4062, fbaf
fa65, 7fffffd2) + fc
00157808 push_back__t6vector2Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_templ
ate2b0i0Zt9allocator1Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0R
Ct12basic_string3ZcZt18string_char_traits1ZcZt24__default (86f2a0, fbaffa20, 7ffffc00, fcbf4062, 1c
, 2d) + 5c
002064b8 getFiles__7ListDirb (86f280, 0, 253800, 4, 1c00, 1d3c) + 12c
<<other stacktrace details truncated>>
. . . .
Из трассировки стека это показывает, что одновременный вызов allocate__t24__default_alloc_template2b0i0Ui
то есть __default_alloc_template<false, 0>::allocate(unsigned int)
терпит неудачу, поскольку это не потокобезопасно.
Эта функция выделения вызывается функцией
simple_alloc<X, __default_alloc_template<false, 0> >::allocate(unsi
gned int)
что в свою очередь называется
_Vector_alloc_base<X, allocator<X>, true>::_M_allocate
(unsigned int)
Я хотел бы переопределить одну из этих трех функций, переопределив функцию распределителя STL в C ++, чтобы обернуть ее как потокобезопасную, защищенную гарантией взаимного исключения.
Пожалуйста, порекомендуйте.
Вы должны синхронизировать свой доступ к контейнерам вместо того, чтобы сделать контейнеры потокобезопасными! Это приведет к кошмару, если вы попытаетесь заново изобрести колесо. Это не только операции вставки и удаления, но также копирование и перемещение элементов, а также параллельная операция над сохраненными элементами.
На самом деле, я считаю, что ваш дизайн не работает, а распределители контейнеров показывают, что ваш Приложение имеет недостатки дизайна.
КСТАТИ: Может быть, вы можете использовать уже реализованные потокобезопасные контейнеры, а не изобретать колесо:
http://libcds.sourceforge.net/
http://www.boost.org/doc/libs/1_55_0/doc/html/lockfree.html
Замечание: я никогда не использовал их и не могу ничего сказать о надежности или других вопросах качества.
Других решений пока нет …