在std::map中搜索时堆栈溢出
stack overflow when searching in std::map
此代码在运行时由于某些原因导致堆栈溢出异常:
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没有运算符<):
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更容易使用,但我更换了它,希望它能引起我的问题。你知道,不可能看穿它返回的类型。这个解决方案可能更难阅读,但它是愚蠢的。
错误:Neural Network.exe中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。
我现在真的很无助。
很抱歉格式不正确。
问题是由无限循环引起的(事实上,这是我见过的堆栈溢出的唯一原因)。
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.
我已经获取了您的代码,并创建了一个可以编译和运行的模型。如果未能根据gcc 4.8.1进行编译,则无法进行模板替换。有一种预感,这与引用包装器的使用有关(并且您正在使用不同的编译器和标准库),我定义了一个运算符<对于类IConnection,并删除了包装器和_CPerceptronComparator。它已编译,并且似乎正在运行。
你可以在这里看到coliru中的代码。
#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将有序映射实现为二进制树,它使用复制构造函数将对象复制到映射(二进制树)中。它使用您提供的比较器(或运算符<)来确定将其插入到何处(稍后再确定如何找到它),但由于您使用对象的地址对其进行排序,并且当它被复制时,这种情况会发生变化-问题!
使用std::shared_ptr是有效的(添加了一个间接级别)。他们说,计算机科学中的任何问题都可以用一种间接的方法来解决——似乎在这里有效。
http://coliru.stacked-crooked.com/a/6aa631675133289b
更新2:
更简单的是,去掉get()
函数,使用指向对象的指针作为映射中的键,直接比较指针的值小于operator<
:
http://coliru.stacked-crooked.com/a/f1376a39c8b287df
- 有根的二进制搜索树.保留与其父级的链接
- 在C++中搜索嵌套多映射值
- cpp二进制搜索问题,计算给定数组中输入元素的出现次数
- 二进制搜索树叶数问题
- 为什么二进制搜索在我的测试中不起作用
- 正在尝试重载二进制搜索树分配运算符
- 算法问题:查找从堆栈中弹出的所有序列
- 使用模板进行堆栈实现; "name followed by :: must be a class or namespace"
- 我可以在没有堆栈的情况下在二叉搜索树中实现迭代器吗?
- C++:如何使用堆栈搜索报价
- 二进制搜索树递归插入导致堆栈溢出,迭代插入不起作用
- 为什么这个二叉搜索树会导致堆栈溢出
- 在迭代深度优先搜索(DFS)算法中确定堆栈大小
- 二进制搜索树创建堆栈-overfow
- 可搜索的堆栈
- 在堆栈中搜索值并存储在临时堆栈中
- 使用堆栈的非递归析构函数二叉搜索树
- 在哪里实现堆栈类(在非递归二进制搜索函数中使用)
- 递归地搜索堆栈,但保持堆栈完整
- 在std::map中搜索时堆栈溢出