通过写入局部变量

时间:2018-07-27 01:11:22

标签: c++ vector attributes local sigsegv

我目前在我的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);
}

2 个答案:

答案 0 :(得分:2)

ASANvalgrind是用于识别此类错误根本原因的工具。即使在第sum += difference行抛出了错误,但在达到这一点之前实际的错误可能在其他地方,这会破坏您的内存。这些工具将帮助您进行跟踪。

答案 1 :(得分:0)

对不起,我错过了一些我应该使用的MultiNEAT框架函数,但没有初始化对象等。无论如何,非常感谢大家,我学到了很多有关使用valgrind和ASAN的知识(两者都非常方便,我之前都不知道它们中的任何一个! h!