因此,我正在用传送和通常的老鼠制作蛇游戏。我有这样的循环运行:

while(snake.alive() && miceEaten < micePerLevel)
{
    displayInfo(lives, score, level, micePerLevel - miceEaten);
    //some code
    if(miceEaten())
    {
        //update score...
    }
    //more stuff...
}

上述代码的问题是 displayInfo 在分数更新之前被调用,因此在吃鼠标后,用户必须等到循环再次运行才能看到他的分数更新。因此,我将一行代码移至函数的底部:

while(snake.alive() && miceEaten < micePerLevel)
{
    //some code
    if(miceEaten())
    {
        //update score...
    }
    //more stuff...
    displayInfo(lives, score, level, micePerLevel - miceEaten);
}

传送者停止工作!每当蛇到达传送时,该程序就会崩溃。和 displayInfo 使用以下代码:

stringstream s;
s << "LEVEL " << left << setw(12) << level << "LIVES: " << setw(12) << lives << "MICE LEFT: " << setw(12) << miceLeft
    << "SCORE: " << setw(13) << score;
printLine(0, s.str(), WHITEONBLUE);

在哪里 printLine 只有一个 color_set, mvprintw, , 和 refresh(). 。与传送无关。奇怪的。

所以我去了蛇功能,蛇从传送中获得下一个位置:

    body.push_back(teleports[overlap(next)]->teleportFrom(dir)); //next is a Location object

在哪里 teleports[overlap(next)]->teleportFrom(dir) 返回蛇要传送到的位置。试图看看为什么它崩溃了(也许 Teleport 在屏幕外返回某个位置吗?),我在上面的行之前添加了以下3行:

    Location l = teleports[overlap(next)]->teleportFrom(dir);
    mvprintw(1, 0, "(%i, %i)", l.x, l.y);
    refresh();

问题消失了!

不仅如此,我还必须拥有这三行。如果我发表评论 mvprintw(1, 0, "(%i, %i)", l.x, l.y);, , 或者 refresh();, ,或两者兼而有之,该程序像以前一样崩溃了。

关于可能导致这种行为的什么想法?

更新: 我尝试删除所有警告(主要是有关签名/未签名数字比较的警告),但到目前为止只有1个:

warning: reference to local variable 'other' returned

和代码:

Location& Location::operator = (Location other)
{
    if(this == &other)
        return other;
    x = other.x;
    y = other.y;
    return *this;
}

我该怎么办来解决此警告?

有帮助吗?

解决方案

这样建立您的作业操作员:
您应该始终返回 *此(即使它们是平等的)。但是,由于您正在创建本地副本,因此他们永远不会(因此这不是您的错误)。

Location& Location::operator = (Location const& other)
{
    // Does it really matter if you assign to self?
    x = other.x;
    y = other.y;
    return *this;
}

对于这样一个简单的类,标准副本和交换似乎有点过大。

PS。您应该修复所有警告(即使它们和未签名的不匹配一样简单)。如果您不修复它们,您将不受其效力的影响,并且不会发现真正的问题,因为它被警告您忽略了。因此,请将它们全部修复(AI始终打开标志,使编译器将所有警告视为错误,以便如果有任何警告,则代码不会编译)。

实施任务操作员的正确方法(或最常见的好方法)。是使用副本和交换成语:

// notice the parameter is passed by value (i.e. a copy).
// So the copy part is aromatically taken care of here.
// So now you just need tom implement the swap() part of the idiom.
Location& Location::operator = (Location other)
{
    this->swap(other);
    return *this;
}

void Location::swap(Location& other)
{
    std::swap(x, other.x);
    std::swap(y, other.y);
}

其他提示

Location& Location::operator = (Location other)
{
    if(this == &other)
        return other;
    x = other.x;
    y = other.y;
    return *this;
}

这返回参考。当功能返回时,会发生什么 other? (它死了,您什么也没提及。)由于这是您在问题区域处理的类,因此这可能是原因。重新安排周围的代码使堆栈处于某个条件,其中指代死变量“工作”。

将其更改为 return *this, ,或者只是完全删除支票。 (分配两个没有分支的变量可能总是比在现代CPU上添加分支更快。)

(您通常还应通过参考而不是副价值来进行参数。)

您是否检查了导致这种异常的代码?这 海森伯格 这里引用的现象:

一个常见的示例是一个在程序中使用优化编译器编译的程序中发生的错误,但在没有优化的情况下编译时不在同一程序中(例如,用于生成调试模式版本)

这里有一些准则:

  • 种族条件?您正在使用线程吗?
  • 指针溢出边界某个地方?
  • 运行您的代码 Valgrind 监视在某处的内存缓冲区中任何异常/不稳定的更改

另一句话:

像海森犬一样行为的一个常见原因是,在调试模式下执行程序通常会在程序启动之前清洁内存,并将变量强制到堆栈位置,而不是将它们放在寄存器中。这些执行方面的差异可以改变涉及涉及内部内存初始内容的错误的错误访问的错误的效果或不正确的假设。另一个原因是,调试器通常提供手表或其他用户界面,这些界面会导致要执行的其他代码(例如属性访问者),从而可以更改程序的状态。另一个原因是Fandango在核心上,这是指针用尽界限的效果。在C ++中,许多Heisenbugs是由非初始化的变量引起的。

确保关闭开关 - 没有优化,完整的调试信息,清除现有的任何构建,重新启动IDE并再次重新编译。

首先,您的位置::操作员=应该像这样:

Location& Location::operator = (const Location &other)
{
    if(this == &other)
        return *this;
    x = other.x;
    y = other.y;
    return *this;
}

但是,这可能无法解释崩溃。堆栈上的不良指针在大多数架构上都不会崩溃(假设X和Y是INT)。

现在,这是一个曼德犬,而不是海森犬。您有其他人在腐败的记忆中。祝你好运。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top