在std :: map中搜索时堆栈溢出

时间:2014-04-13 14:11:49

标签: c++ stack-overflow stdmap

由于某种原因,此代码在运行时导致堆栈溢出异常:

neuralnetwork::CPerceptron::inputEvent(const neuralnetwork::IConnection * origin, double value)
    std::map<std::reference_wrapper<const IConnection>, float64_t, _CPerceptronComparator>::iterator it = m_inputValues.find( std::ref( *origin ) );
    if ( it == m_inputValues.end() )
    {
        throw "Some error";
    }
    ...
}

_CPerceptronComparator看起来像这样(需要它,因为std :: ref没有运算符&lt;):

class _CPerceptronComparator
{
public:
_CPerceptronComparator()
{
}

bool operator()( const std::reference_wrapper<const neuralnetwork::IConnection *> & val1,
                 const std::reference_wrapper<const neuralnetwork::IConnection *> & val2 ) const
{
    return (val1.get()) < (val2.get());
}

bool operator()( const std::reference_wrapper<const neuralnetwork::IConnection> & val1,
                 const std::reference_wrapper<const neuralnetwork::IConnection> & val2 ) const
{
    return &( val1.get() ) < &( val2.get() );
}

bool operator()( const std::reference_wrapper<neuralnetwork::IConnection> & val1,
                 const std::reference_wrapper<neuralnetwork::IConnection> & val2 ) const
{
    return &( val1.get() ) < &( val2.get() );
}
};

我添加了更多代码,所以也许你可以提供帮助。这就是我添加输入连接的方式:

 void CPerceptron::addInputConnection( IConnection * inConn )
 {
    m_outConnections.insert( std::ref(*inConn) );

    m_inputValues.insert( std::pair<std::reference_wrapper<IConnection>, float64_t>( std::ref( *inConn ), 0.0f ) );
    m_isInputReady.insert( std::pair<std::reference_wrapper<IConnection>, bool>( std::ref( *inConn ), false ) );
 }

注意:我知道std :: make_pair更容易使用,但我更换了它,希望它能引起我的问​​题。你知道,它不可能看到它返回的那种类型。这个解决方案可能更难阅读,但是很简单。

错误:神经网络中0x002C2EC9处的未处理异常:0xC00000FD:堆栈溢出(参数:0x00000001,0x00102FFC)。

调用堆栈:

Neural Network.exe!std::_Iterator_base12::_Orphan_me() Line 192 C++
Neural Network.exe!std::_Iterator_base12::_Adopt(const std::_Container_base12 * _Parent) Line 165   C++
Neural Network.exe!std::_Iterator_base12::operator=(const std::_Iterator_base12 & _Right) Line 129  C++
Neural Network.exe!std::_Iterator_base12::_Iterator_base12(const std::_Iterator_base12 & _Right) Line 121   C++
Neural Network.exe!std::_Iterator012<std::bidirectional_iterator_tag,std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double>,int,std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> const *,std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> const &,std::_Iterator_base12>::_Iterator012<std::bidirectional_iterator_tag,std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double>,int,std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> const *,std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> const &,std::_Iterator_base12>(const std::_Iterator012<std::bidirectional_iterator_tag,std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double>,int,std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> const *,std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> const &,std::_Iterator_base12> & __that)    C++
Neural Network.exe!std::_Tree_unchecked_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> > >,std::_Iterator_base12>::_Tree_unchecked_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> > >,std::_Iterator_base12>(const std::_Tree_unchecked_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> > >,std::_Iterator_base12> & __that)   C++
Neural Network.exe!std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> > > >::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> > > >(const std::_Tree_const_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> > > > & __that)    C++
Neural Network.exe!std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> > > >::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> > > >(const std::_Tree_iterator<std::_Tree_val<std::_Tree_simple_types<std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> > > > & __that)  C++
Neural Network.exe!std::_Tree<std::_Tmap_traits<std::reference_wrapper<neuralnetwork::IConnection const >,double,neuralnetwork::_CPerceptronComparator,std::allocator<std::pair<std::reference_wrapper<neuralnetwork::IConnection const > const ,double> >,0> >::find(const std::reference_wrapper<neuralnetwork::IConnection const > & _Keyval) Line 1553  C++
Neural Network.exe!neuralnetwork::CPerceptron::inputEvent(const neuralnetwork::IConnection * origin, double value) Line 94  C++

让我注意一下,如果我调试地图,它应该包含一个元素。 (或者至少它的大小告诉我它有1个元素。)

我用什么类型的迭代来迭代地图并不重要,它会在第一个查询中产生错误。我使用的是Visual Studio 2013。

我现在真的很无助。

抱歉格式不正确。

2 个答案:

答案 0 :(得分:1)

问题是由无限循环引起的(实际上我曾经见过堆栈溢出的唯一原因)。

void CPerceptron::addInputConnection( IConnection * inConn )
{
    m_outConnections.insert( std::ref(*inConn) );

    m_inputValues.insert( std::pair<std::reference_wrapper<IConnection>, float64_t>( std::ref( *inConn ), 0.0f ) );
    m_isInputReady.insert( std::pair<std::reference_wrapper<IConnection>, bool>( std::ref( *inConn ), false ) );
}

我在一个名为addInputConnection的函数中插入m_outConnections,它在图形中创建了一个圆(在神经网络中),因此传播结果导致无限循环(传播函数不在帖子中)。

这是一个很好的例子,很容易错过这么小的东西,但其他无用的帖子。将其删除IMO。

答案 1 :(得分:0)

我已经拿走了你的代码并创建了一个我可以编译和运行的模型。如果在gcc下无法编译4.8.1无法进行模板替换。在预感中这与使用引用包装器(以及您使用不同的编译器和标准库)有关,我定义了一个运算符&lt;对于类IConnection并删除了包装器和_CPerceptronComparator。它已编译,似乎正在运行。

您可以看到code in coliru here

#include <iostream>
#include <map>
#include <stdexcept>

typedef double float64_t;

namespace neuralnetwork {

    class IConnection {
        float64_t _value = 0.0;
    public:
        IConnection( float64_t v ) : _value(v) {}
        float64_t get() const { return _value; }
        friend inline bool operator< ( const IConnection & lhs, const IConnection & rhs ) { return lhs.get() < rhs.get(); }
    };

    class CPerceptron {
        std::map<const IConnection, float64_t>
        m_inputValues, m_isInputReady;
        public:
        void inputEvent(const neuralnetwork::IConnection * origin, double value);
        void addInputConnection( IConnection * inConn );
    };

    void CPerceptron::addInputConnection( IConnection * inConn )
    {
        m_inputValues.insert( std::pair<IConnection, float64_t>( *inConn, 0.0f ) );
    }

} // namespace neuralnetwork

void neuralnetwork::CPerceptron::inputEvent(const neuralnetwork::IConnection * origin, double value)
{
    std::map< const neuralnetwork::IConnection, float64_t >::iterator
        it = m_inputValues.find( *origin );
    if ( it == m_inputValues.end() )
    {
        throw std::runtime_error("Some error");
    }
//   ...
}

int main( int argc, char *argv[] )
{
    neuralnetwork::IConnection ic( 1.0 );
    neuralnetwork::CPerceptron cp;
    cp.addInputConnection( & ic );
    cp.inputEvent( & ic, 2.0 );
    std::cout << "No stack overflow here!" << std::endl;
    return 0;
}

这是我得到的输出

g++-4.8 -std=c++11 -O2 -Wall -pedantic -pthread main.cpp && ./a.out
No stack overflow here!

<强>更新

根据OP的观察,我创建了两个版本,它们使用对象的地址在地图中排序:

在堆栈上创建的对象(失​​败):

http://coliru.stacked-crooked.com/a/02d1f262a75b1d25

在堆上创建的对象(失​​败):

http://coliru.stacked-crooked.com/a/728cf77040143f21

STL将有序映射实现为二叉树,它使用复制构造函数将对象复制到映射(二叉树)。它使用你提供的比较器(或运算符&lt;)来确定插入它的位置(以及后来弄清楚如何找到它),但是因为你正在使用对象的地址来对它进行排序,并且当它被获取时会发生变化复制 - 问题!

使用std :: shared_ptr工作(添加了一个间接级别)。他们说计算机科学中的任何问题都可以通过一个间接层面来解决 - 似乎在这里工作。

http://coliru.stacked-crooked.com/a/6aa631675133289b

更新2:

更简单,摆脱get()函数并使用指向对象的指针作为地图中的关键字,直接比较指针的值小于operator<

http://coliru.stacked-crooked.com/a/f1376a39c8b287df