flysoso / sersync

Automatically exported from code.google.com/p/sersync
1 stars 0 forks source link

RemoveWatch()函数map循环删除好像有点问题 #40

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
这两天在看这个项目的源码,因为最近的开发要用到inotify的�
��性。Inotify 
class里的RemoveWatch()里,PathMap删除的处理有点问题,循环里eras
e后,iterator会失效。正确做法好像是for(;itr != map.end();){ if 
(need_delete) { map.erase(itr++) } else { ++itr};}

Original issue reported on code.google.com by tod...@gmail.com on 26 Aug 2010 at 10:58

GoogleCodeExporter commented 8 years ago
源码里如下:我这么写应该是重新赋值了啊?能说具体点么��
�你的写法好像迭代器没有重新赋值啊。
/*
 *input params: string  path not end up with slash /opt/tongbu/temp
 *function:     remove the path from watching deque
 *return:      success true else false;
 */
bool Inotify::RemoveWatch(std::string path)
{
    bool finded = false;
    for ( PathMap::iterator i = m_path.begin(); i != m_path.end(); i++ )
    {
        if ( i->second.substr(0, path.length()) == path ) //查找已经添加的监控
        {
            if ( (i->second[ path.length() ]) == '/' || i->second[ path.length() ] == 0 )//ignore the error /1234/123/  1234/12/ as the same directory tree
            {
                inotify_rm_watch(m_fd, i->first);
                m_path.erase(i);
                finded = true; //找到并删除
            }
        }
    }
    if ( !finded ) return false;
    return true;
}

Original comment by zhouyang...@gmail.com on 27 Aug 2010 at 4:32

GoogleCodeExporter commented 8 years ago
map在循环里删除的时候,迭代器会失效。map.erase()返回的是下
一个迭代节点的位置。如果直接删除map.erase(i),再用++i的话��
�会出现不可预知的错误。所以一般不在循环条件里去累加,�
��是通过判断是否有删除,如果有的话,两种方式,一种是先
累加记住下一个位置,再删除,即m_path.erase(i++),另一种是直��
�用erase的返回值 i=m_path.erase(i)。
也就是说,在删除的时候,再去用原来的iterator累加,会出问
题。上面我为了示意,写的比较简单,itr先用map里的第一个��
�值,迭代器在循环体内递增。可能我说的不是很清楚,可以g
oogle "map erase"。

Original comment by tod...@gmail.com on 29 Aug 2010 at 2:14

GoogleCodeExporter commented 8 years ago
尝试改过后的代码

bool Inotify::RemoveWatch(std::string path)
{
    bool finded = false;
    PathMap::iterator i = m_path.begin();
    for ( ; i != m_path.end();  )
    {
        if ( i->second.substr(0, path.length()) == path ) //查找已经添加的监控
        {
            if ( (i->second[ path.length() ]) == '/' || i->second[ path.length() ] == 0 )//ignore the error /1234/123/  1234/12/ as the same directory tree
            {
                inotify_rm_watch(m_fd, i->first);
                m_path.erase(i++);
                finded = true; //找到并删除
            } 
            else
            {
              ++i;
            }
        }
        else
        {
           ++i;
         }
    }
    if ( !finded ) return false;
    return true;
}

Original comment by tod...@gmail.com on 29 Aug 2010 at 2:19

GoogleCodeExporter commented 8 years ago
好的,多谢。有bug。
tip:
对了inotify 
api说,如果有删除的目录,它回自动rm_watch,我记得我只是自
己手动又remove 
watch了,但好像这段代码没有起到应有的作用。

Original comment by zhouyang...@gmail.com on 30 Aug 2010 at 12:41

GoogleCodeExporter commented 8 years ago
谢谢你的分享 :)
PathMap这个是你自己维护的记录。如果inotify 
会自动rm_watch 的话,删除的是系统watch 
list里东东,只是上面那个函数里的系统调用inotify_rm_watch会重
复。。这个函数还是会删除PathMap的

Original comment by tod...@gmail.com on 30 Aug 2010 at 2:52