C ++无法修改类的实例

时间:2014-04-02 12:44:22

标签: c++ class instance

在以下线程例程中:

void*   Nibbler::moveRoutine(void* attr)
{
  [...]
      Nibbler*  game = static_cast<Nibbler*>(attr);

      while (game->_continue == true)
       {
         std::cout << game->_snake->_body.front()->getX() << std::endl; // display 0
         std::cout << game->getDirection() << std::endl; // display 0
         game->moveSnake();
         std::cout << game->_snake->_body.front()->getX() << std::endl; // display 0
         std::cout << game->getDirection() << std::endl; // display 42
       }
    }
  [...]
}

我正在调用成员函数moveSnake(),它应该修改形成我蛇体的细胞的位置。

void    Nibbler::moveSnake()
{
  [...]
  std::cout << this->_snake->_body.front()->getX() << std::endl; // display 0
  this->_snake->_body.front()->setX(3);
  this->_direction = 42;
  std::cout << this->_snake->_body.front()->getX() << std::endl; // display 3
  [...]
}

尽管我的两个坐标在我的moveSnake()函数中被有效修改,但当我回到我的例行程序时,它们不再是它们保持初始值。我不明白为什么会发生这种情况,因为如果我尝试在我的moveSnake()函数中修改我的类的任何其他值,则修改该实例并将该值保留在例程中。

Nibbler班:

class Nibbler
{
public :
  [...]
  void          moveSnake();
  static void*  moveRoutine(void*);

private :
  [...]
  int           _direction
  Snake*        _snake;
  IGraphLib*    _lib;
  pthread_t     _moveThread;
...
};

蛇:

class   Snake
{
public :

  [...]
  std::vector<Cell*>    _body;
};

最后是细胞:

class   Cell
{
public :

  void  setX(const int&);
  void  setY(const int&);

  int   getX() const;
  int   getY() const;

  Cell(const int&, const int&);
  ~Cell();

private :

  int   _x;
  int   _y;
};

cell.cpp代码:

void        Cell::setX(const int& x)
{
  this->_x = x;
}

void        Cell::setY(const int& y)
{
  this->_y = y;
}

int     Cell::getX() const
{
  return this->_x;
}

int     Cell::getY() const
{
  return this->_y;
}

Cell::Cell(const int& x, const int& y)
{
  this->_x = x;
  this->_y = y;
}

Cell::~Cell()
{}

1 个答案:

答案 0 :(得分:2)

从表面上看,你的问题(“为什么这个成员什么时候不应该被修改?”)似乎是合理的。所展示的设计意图已经足够清晰,我认为它符合您的描述。但是,你的程序中的其他元素却合谋使其不是这样。

可能困扰你的一件事是Undefined Behavior。信不信由你,即便是最有经验的C ++开发人员偶尔会与UB发生冲突。此外,堆栈和堆损坏是非常容易导致非常难以隔离的问题的方法。你有几件事要转向,以便根除它:

调试器(从这里开始!)

  • 使用简单的单步调试器,您可以遍历代码并在每个转弯处检查您的假设。设置一个断点,执行直到,检查内存/变量的状态,再次平分问题空间,迭代。

静态分析

  • 从编译器警告开始,升级到lint和复杂的商业工具,静态分析可以帮助指出可能不一定是UB的“代码味道”,但可能是死代码或代码可能不执行的其他地方你认为它的作用。
  • 您是否忽略了您正在调用的库/操作系统返回的错误?在你的情况下,似乎你直接操纵记忆,但这是期望与现实之间不匹配的常见原因。
  • 你有rubber duck方便吗?

动态分析

  • 像Electric Fence / Purify / Valgrind(memcheck,helgrind)/ Address-Sanitizer,Thread-Sanitizer / mudflaps这样的工具可以帮助识别你在已经分配的内容之外写入内存的区域。

如果您尚未使用调试器,那么这是您的第一步。如果您以前从未使用过,那么现在是您必须暂停一段时间并了解如何使用的时间。如果你计划超出这个水平,你会感激你的。

如果您在Windows上进行开发,则很有可能使用Visual Studio。调试器很可能很好地集成到您的IDE中。把它点起来!

如果您正在使用linux / BSD / OSX进行开发,则可以访问gdbXCode,这两者都应该足够简单来解决此问题。阅读教程,观看视频,做任何事情并让调试器滚动。您可能很快发现您的代码一直在修改Snake的一个实例并打印出另一个实例(或同样令人沮丧的内容)。

如果在使用调试器时无法复制问题条件,请恭喜!您找到了heisenbug。它可能表示race condition,仅此信息将帮助您了解问题的根源。