【问题标题】:segmentation fault in iterator of std::liststd::list 迭代器中的分段错误
【发布时间】:2013-07-23 21:09:49
【问题描述】:

类声明

struct cmp_str
{
 bool operator()(char const *a, char const *b)
 {
    return std::strcmp(a, b) < 0;
 }
};

class event_t {
public:
  event_t(String *_session_time, String *_event_type, String *_table_name, String *_num_of_events);
  ~event_t();
   char *table_name;
   char *event_type;  
   pthread_mutex_t lock;
   pthread_cond_t cond;
   int num_of_events_threshold;
   double time_out; 
   int num_of_events_so_far; 
};  
std::map <char*, std::list<event_t*>, cmp_str > all_events;  //global map

我有这个函数,它等待一个变量达到某个阈值,这是通过 pthread_cond 和 pthread_mutex 完成的。然后它返回。最后一行给出了分段错误。

void foo(){
    //don't worry event object ic created properly
    event_t *new_event = new event_t(args[0]->val_str(s),(args[1]->val_str(s)), (args[2]->val_str(s)), (args[3]->val_str(s)));

    map<char*, list<event_t*> >::iterator map_it;  
    map_it = all_events.find(new_event->table_name);

    if(map_it == all_events.end()){
      list<event_t*> *my_list = new list<event_t*>();
      my_list->push_back(new_event);
      all_events[new_event->table_name] = *my_list;
    }
    else{
      map_it->second.push_back(new_event);
      for (list<event_t*>::iterator list_it=map_it->second.begin(); list_it!=map_it->second.end(); ++list_it)
        std::cout << (*list_it)->event_type << " " << (*list_it)->time_out << " " << (*list_it)->num_of_events_threshold << '\n';
    }


/*
* waiting for number of events reach its threshold.
*/
    pthread_mutex_lock(&new_event->lock);

    while(new_event->num_of_events_so_far < new_event->num_of_events_threshold )
      pthread_cond_wait(&new_event->cond, &new_event->lock);
    pthread_mutex_unlock(&new_event->lock);
    // segmentation fault!!!
    for (list<event_t*>::iterator list_it=map_it->second.begin(); list_it!=map_it->second.end(); ++list_it)
        std::cout << (*list_it)->event_type << " " << (*list_it)->time_out << " " << (*list_it)->num_of_events_threshold << '\n';
}   

【问题讨论】:

  • 你初始化你的互斥锁了吗?
  • 是的,它已经在 event_t 类的构造函数中初始化了。
  • 当您将新事件列表添加到主地图时,您似乎从未将map_it 设置为新添加的条目。因此,当您到达 for 循环并尝试使用迭代器时,您将取消引用 end()
  • 请注意,比较两个char *s 只比较指针,而不是内容。您的 map 可能无法按您想要的方式工作。
  • 我完全同意 avakar 的说法。您提供自己的比较器,这很好,但老实说,这些都不应该是char*。理想情况下,您应该使用std::string,此时默认比较器就足够了。并使用实例级列表,而不是指向列表的指针。

标签: c++ iterator segmentation-fault stdlist


【解决方案1】:
if(map_it == all_events.end()){
  list<event_t*> *my_list = new list<event_t*>();
  my_list->push_back(new_event);
  all_events[new_event->table_name] = *my_list;
}

这段代码不会让map_it 指向一个有效的迭代器,所以当你在函数底部取消引用它时,它会崩溃。

你可能想添加一行

map_it = all_events.find(new_event->table_name);

if { } 子句中。

【讨论】:

  • +1(出于显而易见的原因,根据我的全球评论)。或者,他可以使用从insert() 返回的std::pair&lt;iterator,bool&gt; 来重新获取正确的迭代器,而无需执行额外的搜索。
  • 这样就解决了问题。但是,我还有另一个问题,我将首先尝试解决。谢谢你,我不能投票,因为我需要至少 15 名声望。
猜你喜欢
  • 2018-03-23
  • 1970-01-01
  • 2014-11-08
  • 1970-01-01
  • 2020-06-09
  • 1970-01-01
  • 2017-10-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多