构造函数中的数组设置意味着稍后失败

时间:2013-02-28 10:47:50

标签: c++ arrays constructor

我遇到了一个问题,我的代码在试图使用列表的size()函数时发生了分歧。根据stackoverflow的建议:-)我构建了一个最小的情况,其中发生了segfault(在下面的调用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 个答案:

答案 0 :(得分: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;之间循环。

答案 1 :(得分:2)

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

使数组大小为100:

int xpCalcArray[100];

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

答案 2 :(得分:2)

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

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

答案 3 :(得分:1)

xpCalcArray定义为0到98(99个元素大)。

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

最后一个循环周期,将xpCalcArray写入位置99,该位置不存在。这(间接)导致您的细分错误,如the answer of Lightness Races in Orbit所示。

因此,将xpCalcArray的大小增加1:

int xpCalcArray[100];