动态位集,导致程序崩溃

3
我对boost不太熟悉。我的一个程序在lambda函数内部使用了dynamic_bitset。当我尝试运行程序时,出现了以下消息。即使没有初始化bitset或处理它的函数,该消息也会出现。
请问有人知道这个消息的含义以及可能的问题是什么?
消息内容如下:

/usr/include/boost/dynamic_bitset/dynamic_bitset.hpp:616: boost::dynamic_bitset<Block, Allocator>::~dynamic_bitset() [with Block = long unsigned int, Allocator = std::allocator<long unsigned int>]: Assertion 'm_check_invariants()' failed. Aborted

代码大致如下: 程序的主调用函数:
int Molecule::initSimilarity(int depth){
    cout << "_size is: " << _size << "\t depth is: " << depth << endl; //TODO delete
    AtomSet viewing(_size);
    int m = 0;
    {
        // break into initial groups by symbol and valancy
        for(int i=0 ; i<_size ; i++)
        {
            if(viewing[i]) continue;
            AtomSet mask = getSetMask( //AtomSet is typedef for dynamic_bitset
                [&](const Atom& b)->bool
                {
                    return (!viewing[b._index] && b._valence == _atoms[i]->_valence && strcmp(b._symbol, _atoms[i]->_symbol) == 0);
                },
                [&](Atom &b)
                {
                    b._class = m; //set the equivalence class of atom 'b' to 'm'
                }
            );
            m++;
            viewing |= mask; //viewing now contains a set of atoms and for each atom it's equivalence class
        }
        cout << "number of equivalence class: " << m << endl; //TODO DELETE!
    }    
    for (int j = 0; j < depth ; j++){
        AtomSet viewed(_size);

        int before = m;
        // iteratively refine the breakdown into groups
        for (int i = 0 ; i < _size ; i++)   //for any atom A
        {
            if (viewed[i]) continue;
            viewed.flip(i);
            AtomSet mask = getSetMask(//put all atoms which are equivalnt but not similar to A in
                //their own equivalence class
                [&](const Atom& b)->bool
                {
                    if (viewed[b._index])
                        return false; //if b is in viewed return false;
                    if (_atoms[i]->_class == b._class) //if in the same class add b to viewed
                    {
                        viewed.flip(b._index);
                        bool similar = !isSimilar(*_atoms[i],b);
                        return similar;
                    }
                    return false;
                },
                [&m](Atom& b)
                {
                    b._class = m;
                }
            );
            if (!mask.none()) m++;
        }
        if (before == m){
            std::cout << "Finished early after just " << j << " iterations" << std::endl;
            return m;
        }
    }
    return m;
}

getSetMask的签名是: AtomSet getSetMask(std::function property, std::function action);

即使我删除该函数的所有内容,仍然会收到错误消息,这是最奇怪的事情。


4
如果你想让别人找到代码中的 bug,你应该发布导致错误的代码。 - sth
1
如果在没有那个函数的情况下仍然出现错误,则问题的根本原因可能不在该函数中。此外,代码中没有提到任何“dynamic_bitset”。另外:getSetMask()函数对这些lambda函数做了什么?它会将它们存储在某个地方吗? - sth
对不起,你是正确的。AtomSet 是 dynamic_bitset 的 typedef。我会进行编辑。 - or.nomore
5个回答

3
我曾经也遇到过这个问题,花了我三个小时才找出了问题所在。以下是可能会发生的情况:在dynamic_bitset中,operator[]不会进行边界检查。因此,可以分配一个超出允许范围的值,但这并不会创建任何错误(sanitizer/valgrind没有发现任何问题),因为dynamic_bitset使用64位整数(至少在我的电脑上)来存储值。因此,在dynamic_bitset中允许4位的情况下,你可以得到一个存储的32位整数。当例如调用析构函数时,m_check_invariant()会触发错误。

因此,解决问题就变成了找到这个范围错误。解决方法是编辑boost/dynamic_bitset.hpp并在operator[]代码中添加打印语句,以便在调用超出范围的操作时进行提示。如果你无法操作,请下载boost库并将其安装在你的主目录中。


3

可能你在lambda表达式中引用的dynamic_bitset变量已经超出了其作用域并且已经被销毁,或者类似的情况。 (没有源代码很难具体说明)


2

我曾经遇到过一个与dynamic_bitset相关的类似问题,解决方法是在它被销毁之前调用reset()函数。


我也遇到了类似的问题,不知道你们是否能够找出根本原因,因为调用重置看起来像是一个临时解决方案。 - user1918858

0

这可能意味着您在未调整大小的情况下写入了位集的末尾。建议进行一些边界检查。


0

阅读Mathieu Dutour Sikiric的解释。问题在于您通过operator[]写入了bitset允许范围之外的内容,但这不会创建任何错误,因为它是boost,并且不会浪费计算时间检查您是否有权在想要的位置进行写入。你知道这是C++...

因此,要检测它,请转到boost/dynamic_bitset/dynamic_bitset.hpp,并修改代码以在每次使用operator[]时强制执行检查。

boost/dynamic_bitset/dynamic_bitset.hpp,大约在第300行。

    reference operator[](size_type pos) {
        assert(m_check_invariants());
        return reference(m_bits[block_index(pos)], bit_index(pos));
    }
    bool operator[](size_type pos) const { 
        assert(m_check_invariants());
        return test(pos); 
    }

这使得在您的代码中检测错误更加容易。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接