我的旧版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)
我想覆盖这三个函数之一,fpr 覆盖C++ STL 分配器函数,以将其包装为在互斥保证下受线程安全保护。请指教。
您应该同步对容器的访问,而不是使容器线程安全!如果你试图重新发明轮子,它最终会陷入噩梦。不仅有插入和删除操作,还有元素复制和移动以及对存储元素的并发操作。
事实上,我相信你的设计是破碎的,容器分配器只表明你的应用程序有设计缺陷。
顺便说一句:也许你可以使用已经实现的线程安全容器,而不是重新发明轮子:
http://libcds.sourceforge.net/
http://www.boost.org/doc/libs/1_55_0/doc/html/lockfree.html
备注:我从未使用过它们,也不能说任何关于鲁棒性或其他质量问题的事情。