我目前在C++项目中遇到了最奇怪的行为。我想做的是计算两个双向量之间的欧氏距离(实际上,是双向量的向量,因此是m_Data[0].size(((
这是来源:
double NEAT::Behavior::Distance_To(NEAT::PhenotypeBehavior* other)
{
double sum = 0.0;
for (int i = 0; i < m_Data[0].size() && i < other->m_Data[0].size(); i++) {
double x1 = m_Data[0][i];
double x2 = b->m_Data[0][i];
double difference = x1 - x2;
difference *= difference;
sum += difference;
}
return sqrt(sum);
}
我最初把所有这些都写在一行中,但我已经把它分解来定位错误。发生的情况是,在对该函数进行几千次调用后,它在for循环的最后一行抛出一个SIGSEGV:
sum += difference;
我不知道这怎么会发生。我已经检查了堆栈跟踪,它来自Distance_To(…(函数,它被精确地抛出到这一行。我一评论出来,一切都很好(但当然这个功能不起作用,哈哈(。每次我在相同对象交互的情况下运行程序时,信号都会在同一时间抛出。
非常感谢您的帮助。谢谢
编辑:我已经通过在进入循环之前打印出所需的值来验证这个方法中指针的完整性。正确打印所有值。以下是我用于调试目的的函数的完整版本:
double NEAT::Behavior::Distance_To(NEAT::PhenotypeBehavior* other)
{
double sum = 0.0;
Behavior* b = (Behavior*) other;
// Gets executed without any problems
if (genomeid == 300 && b->genomeid == 399) {
std::cout << "PROBLEM CASE" << std::endl;
std::cout << "Printing values for 300..." << std::endl;
for (int i = 0; i < m_Data[0].size(); i++) std::cout << m_Data[0][i] << std::endl;
std::cout << "Printing values for 399..." << std::endl;
for (int i = 0; i < m_Data[0].size(); i++) std::cout << b->m_Data[0][i] << std::endl;
}
// Doesn't get executed
if (m_Data[0].size() != other->m_Data[0].size()) {
std::cout << "Different sizes, " << m_Data[0].size() << " and " << b->m_Data[0].size() << std::endl;
}
// SIGSEGV at size() call
for (int i = 0; i < m_Data[0].size() && i < b->m_Data[0].size(); i++) {
double x1 = m_Data[0][i];
double x2 = b->m_Data[0][i];
double difference = x1 - x2;
difference *= difference;
// If this line gets commented out, no SIGSEGV but the program starts behaving weirdly afterwards (suddenly different sizes after the faulty run)
sum += difference;
}
return sqrt(sum);
}
ASAN和valgrind是您应该用来确定此类错误的根本原因的工具。即使在sum += difference
行出现错误,在达到破坏记忆的点之前,您的实际错误可能在其他地方。这些工具将帮助您跟踪。
对不起,伙计们,我错过了一些MultiNEAT框架函数,我本应该使用这些函数,但没有用于初始化对象等。无论如何,非常感谢你们,我学到了很多关于使用valgrind和ASAN的知识(这两个都很方便,我以前都不知道!哈哈(,甚至还有一些好文章可以阅读。啊!