【发布时间】:2014-04-11 00:58:07
【问题描述】:
我有一个多线程应用程序,我使用 std::map 来存储键值对。虽然我使用互斥锁(pthread,因为不使用 C++11)保护对 std::map 的访问以确保互斥,但基于数据的密钥在互斥块之外。这是因为我的密钥制作是在本地完成的,而不是使用共享数据。我有一个小的实用函数 mkkey,它按值返回一个字符串,定义如下:
std::string mkkey(char *n1, char *n2, int d) {
char buff[200];
sprintf(buff, "%s:%s:%d", n1, n2, d);
return buff;
}
mkkey 的参数不是 null 并且是有效的字符串,在大小限制内,所以我不会超过缓冲区大小。但是,我遇到了崩溃,pstack 核心显示以下内容: 对于一个线程:
--- called from signal handler with signal 10 (SIGBUS) ---
00271340 allocate__t24__default_alloc_template2b0i0Ui (30, 30, 10, 2, 1, 0) + a4
0015ec84 __nw__Q2t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0_3RepUiUi (10, 20, 1, 2, 1, 1) + 14
0015fa44 create__Q2t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0_3RepUi (19, 19, 664e10, fc27b694, ffbff790, fffc00) + 24
0016c71c replace__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0UiUiPCcUi (fc27b888, 0, ffffffff, fc27b038, 19, 80808080) + 114
002af8c4 assign__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCcUi (fc27b888, fc27b038, 19, fc27b051, 1, 1) + 24
0029b380 assign__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCc (fc27b888, fc27b038, 7fffffe6, 664e10, fc27b051, 7fffffe6) + 24
00263600 __t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCc (fc27b888, fc27b038, 7ffffc00, 664e10, fc27b895, 19) + 28
0012caec mkKey__FRC8UserData (fc27b890, fc27b888, fc27b8a1, 0, ff000000, 80808080) + f4
对于另一个线程:
----------------- lwp# 7 / thread# 7 --------------------
0025b148 data__Q2t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0_3Rep (84f970, 4631bc, 1, 2, 1, 0) + 4
001616c8 copy__Q2t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0_3RepUiPCcUi (84f970, 0, fbe7b0c8, 19, ffbff790, fffc00) + 24
0016c7a8 replace__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0UiUiPCcUi (fbe7b918, 0, ffffffff, fbe7b0c8, 19, 80808080) + 1a0
002af8c4 assign__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCcUi (fbe7b918, fbe7b0c8, 19, fbe7b0e1, 1, 1) + 24
0029b380 assign__t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCc (fbe7b918, fbe7b0c8, 7fffffe6, 664e10, fbe7b0e1, 7fffffe6) + 24
00263600 __t12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0PCc (fbe7b918, fbe7b0c8, 7ffffc00, 664e10, fbe7b925, 19) + 28
0012caec mkKey__FRC8UserData (fbe7b920, fbe7b918, fbe7b931, 0, ff000000, 80808080) + f4
崩溃的线程似乎在通常表示访问无效地址的 SIGBUS 上崩溃。会出什么问题?由于 mkkey 按值返回而形成的 std::string 应该重新创建一个 std::string,但它表明 alloc 失败。它与std :: string有关吗?在使用少量数据进行调试时,我没有看到任何明显的问题,问题来自于更大的数据量。堆大小可能是导致同步分配失败的问题吗?还是 std::string 本身?我故意将 mkkey 保留在互斥锁之外,因为它是在本地完成的,而不是在共享数据上完成的。
【问题讨论】:
-
“堆大小可能是个问题吗?” - 不,但堆栈大小可以(在本文中描述的特定情况下)。
-
@barakmanos 在这种情况下,可能会尝试增加线程堆栈大小,因为我使用 pthread 分配的默认堆栈大小
-
也许这些论点并没有您认为的那么有效?至少使用
snprintf(当然,使用 C++ 范例会更好)。您能否尝试将您的程序精简为一个可以完整发布但仍会崩溃的最小示例?
标签: c++ string multithreading new-operator