c++ - 尝试在 hash_map 中查找记录时应用程序崩溃

标签 c++ string multithreading stl hashmap

我有一个多线程应用程序,它使用 C++ STL hash_map 来存储键值对。 hash_map 定义如下:

struct eqstr
{
  bool operator()(const string& s1, const string& s2) const
  {
    return (s1 == s2);
  }
};
typedef hash_map<string,UserData, hash<string>, eqstr> DataMap;
DataMap datamap; 

其中,UserData 是一个简单的结构类型,具有

struct UserData
{
    char id[4+1];
    char date[20+1];
    int mode;
};

在我的申请中,我有

bool found = true;
pthread_mutex_lock(&muCS);
DataMap::iterator itr;
itr = datamap.find(key); // key is a string
if (itr == datamap.end()) 
  found = false;
pthread_mutex_unlock(&muCS);

当应用程序运行时,我偶尔会崩溃,pstack core 显示如下:

--- called from signal handler with signal 11 (SIGSEGV) ---
 ff31db18 assign__t18string_char_traits1ZcRcRCc (fc07b958, 877f48, 877f58, 2, 1, 662fc0) + 8
 00263f24 c_str__Ct12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0 (fc07b958, 83af88, fc07b0c8, 1a, ffbff778, fffc00) + 34
 00346c34 __cl__Ct4hash1Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0RCt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0 (77fd59, fc07b958, ffffffff, fc07b0c8, 1a, 80808080) + 18
 00346900 _M_bkt_num_key__Ct9hashtable6Zt4pair2ZCt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0Z8UserDataZt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0Zt4hash1Zt12basic_string3ZcZt18strin (77fd58, fc07b958, c005, fc07b0e2, 1, 1) + 1c
 00346960 _M_bkt_num_key__Ct9hashtable6Zt4pair2ZCt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0Z8UserDataZt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0Zt4hash1Zt12basic_string3ZcZt18strin (77fd58, fc07b958, cc, fc551200, ff2c2030, 10000) + 28
 00347140 find__t9hashtable6Zt4pair2ZCt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0Z8UserDataZt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0Zt4hash1Zt12basic_string3ZcZt18string_char_trai (77fd58, fc07b958, fc551a00, 6633d0, 2922e4, 6633d8) + 18
 003469f0 find__t8hash_map5Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0Z8UserDataZt4hash1Zt12basic_string3ZcZt18string_char_traits1ZcZt24__default_alloc_template2b0i0Z5eqstrZt9allocator1Z8UserDataRCt12basic_s (77fd58, fc07b958, fc07b910, 0, 6633d0, 26a0bc) + 1c

因此,在 hash_map 中查找 STL 字符串似乎失败了。 我有带信号量的标准守卫以确保互斥。 会出什么问题? 任何补救建议或任何解决方法都会有很大帮助。您是否觉得 hash_map 需要更改为一些更好的数据结构或任何其他解决方法以防止 STL 字符串崩溃? 提前致谢。

最佳答案

我将执行以下操作来修复崩溃:

  1. 如果您没有 c++11,请将 hash_map 更改为 std::map,或者更改为 std::unordered_map
  2. 如果您有 c++11,请使用 std::mutexstd::unique_lock 而不是 pthread_* 函数。 pthread_mutex_lock 这里有两个问题:它们不是异常安全的(如果在 pthread_mutex_lockpthread_mutex_unlock 之间会产生一些异常,mutex 永远不会解锁,你会遇到死锁),并且你不检查这个函数的返回值(如果你的互斥量不能被锁定,或者没有正确初始化,你永远不会知道,错误将被默默地忽略,你会得到数据竞赛)。
  3. 检查是否在 pthread_mutex_unlock 方法之后使用了 itr。即使搜索操作已完成,您仍然可以进行数据竞争,因为不同的线程可以尝试更新迭代器指向的值。所以这个操作也应该受到互斥锁的保护。
  4. 检查您的 map 的所有访问是否都受到一个互斥体的保护。如果您发现它无效,之后您可以随时更改锁类型(例如读/写锁)或为每个 UserData 添加一个锁。
  5. 检查您的代码设计。将您的 map 容器添加到一个类中并将其设为私有(private)。这样您就可以控制对它的访问。向此类添加一个互斥锁,然后在访问映射之前,只需检查该类的所有公共(public)方法中的互斥锁是否已锁定一次。

如果有帮助,请回信。

关于c++ - 尝试在 hash_map 中查找记录时应用程序崩溃,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22197915/

相关文章:

c++ - 一些 C++ vector 问题

java - 如何在程序运行时更新GUI?

swift - 如何在 Swift 中创建自定义完成 block

java - 使用 ExecutorService 的并发

c++ - "Vector iterator not incrementable"错误

删除节点的 C++ 二叉搜索树错误

c++ - 在 C++ 中获取 WMI 查询的行数

c++ - Eclipse 显示错误,但 gcc 编译正常

javascript - 用于时间跟踪的正则表达式验证

c# - 如何将一个大数字作为一个字符串递增,就好像它是一个整数一样?