7

我遇到了一个问题,即我的代码在尝试使用列表的 size() 函数时出现段错误。根据 stackoverflow 的建议 :-) 我构建了一个发生段错误的最小情况(在下面的调用 inventory.size() 上)。这是:

#include <list>

class Thing {};

class Player {
private:
  int xpCalcArray[99];
  std::list<Thing*> inventory;

public:
  Player();

  int addToInv(Thing& t); // return 1 on success, 0 on failure
};

Player::Player() {
  // set up XP calculation array
  for (int i=1; i<100; i++) {
    if (i<=10) {
      xpCalcArray[i] = i*100;
    }
    if (i>10 && i<=50) {
      xpCalcArray[i] = i*1000;
    }
    if (i>50 && i<=99) {
      xpCalcArray[i] = i*5000;
    }
  }
}

int Player::addToInv(Thing& t) {
  if (inventory.size() == 52) {
  return 0;
  } else {
      inventory.push_back(&t);
  }
  return 1;
}

int main(int argc, char *argv[]) {
  Thing t;
  Player pc;
  pc.addToInv(t);
  return 1;
}

我注意到,当我删除 Player cosntructor 中的数组设置时,它工作正常,所以这看起来是问题所在。我究竟做错了什么?

4

4 回答 4

4

您正在越界访问数组,这会导致未定义的行为。此数组的有效索引范围

int xpCalcArray[99];

是 0 到 98。您在此处访问索引 99:

if (i>50 && i<=99) {
  xpCalcArray[i] = i*5000;
}

你的外循环应该是

for (int i=0; i<99; i++) { ... }

请注意,我从 0 开始,尽管假设您实际上想要访问第一个元素。

然后您的最终条件可以简化为

if (i>50) {
  xpCalcArray[i] = i*5000;
}

如果您打算使用大小为 100 的数组,那么您需要

int xpCalcArray[100];

然后在int i=0; i<100;.

于 2013-02-28T10:49:28.503 回答
2

您正在访问数组范围之外。这样做会导致未定义的行为,因此对于之后发生的任何事情都没有合乎逻辑的解释。数组的大小是 99,因此最后一个索引是 98。for但是,您的循环会上升到 99。

要么让你的数组大小为 100:

int xpCalcArray[100];

或将您的for条件更改为i < 99.

于 2013-02-28T10:50:06.273 回答
2

int通过尝试修改第 2 个→第 100 个元素(而不是第 1 个→第 99 个)来覆盖您的 99 数组。

在您的情况下,这恰好覆盖了其中的一些内存std::list<Thing*>(它直接存在于数组之后的内存中 -并非总是如此,但今天显然对您而言),因此,当您尝试使用列表时,当它的内部成员时,一切都会崩溃数据不再是它想象的那样。

于 2013-02-28T10:51:42.293 回答
1

xpCalcArray的定义范围为 0 到 98(即 99 个大元素)。

您的循环从 0 到 99,需要 100 步。

最后一个循环周期,xpCalcArray在不存在的位置 99 处写入。这(间接)导致您的分段错误,如轨道中的 Lightness Races 的答案所示。

因此,将 的大小增加xpCalcArray1:

int xpCalcArray[100];
于 2013-02-28T10:52:00.223 回答