std::vector push_back 上的 Segfault/“向量不可解引用”
Posted
技术标签:
【中文标题】std::vector push_back 上的 Segfault/“向量不可解引用”【英文标题】:Segfault/ "Vector is not dereferencable" on std::vector push_back 【发布时间】:2013-09-09 20:02:14 【问题描述】:我有一些处理纸牌游戏的 C++ 代码,它出现了段错误,我不知道为什么。我尝试在 MSVS 2012 中运行它以获得更清晰的错误,但它抛出了“Vector is not dereferencable”。我试着做一些研究,但我不知道错误来自哪里。我猜这个错误不在 push_back 中,而是在其他地方,因为问题线大部分时间都有效。错误发生在 Table::hit() 中。查看代码后,我认为该错误可能存在于 Hand::split() 中,但我不确定,我更不确定如何修复它。谢谢!
class Hand
public:
std::vector<Card> hand;
bool active, doubled, isBlackjack, busted;
Hand() : active(true), doubled(false), isBlackjack(false), busted(false)
Hand(const Hand& _hand);
void removeCard(Card card) hand.erase( hand.begin() );
Card split();
void clear();
int cards() const return hand.size();
int getHandValue() const;
Card at(int pos) return hand[pos];
friend std::ostream& operator<< (std::ostream& out, const Hand& hand);
friend std::ostream& operator<< (std::ostream& out, const std::vector<Hand>& hands);
;
Hand::Hand(const Hand& _hand)
: hand(_hand.hand), active(_hand.active), doubled(_hand.doubled), isBlackjack(_hand.isBlackjack), busted(_hand.busted)
Card Hand::split()
//COULD THE BELOW CODE BE CAUSING ISSUES?
Card card = hand[0];
hand.erase( hand.begin() );
return card;
void Hand::clear()
active = true;
hand.clear();
int Hand::getHandValue() const
int value(0), aces(0);
for(std::vector<Card>::const_iterator it = hand.cbegin(); it != hand.cend(); ++it)
value += getCardValue(it->getRank());
if(it->getRank() == ACE)
++aces;
while(aces > 0 && value > 21)
value -= 10;
--aces;
return value;
std::ostream& operator<< (std::ostream& out, const Hand& hand)
for(std::vector<Card>::const_iterator it = hand.hand.begin(); it != hand.hand.end(); ++it)
out << *it << " ";
out << hand.getHandValue();
return out;
std::ostream& operator<< (std::ostream& out, const std::vector<Hand>& hands)
for(std::vector<Hand>::const_iterator it = hands.begin(); it != hands.end(); ++it)
out << *it << " ";
return out;
class Table
protected:
Shoe shoe;
Strategy strat;
Hand dealer;
std::vector< Hand > player;
double balance, blackjackPayoff;
bool hitSoft17;
void deal();
void hit(int split=0);
void split(int split=0);
double stand();
Action getUserAction();
bool isCurrentGame();
public:
Table(int decks, int _balance);
double bet;
void play();
void print();
void simulate(std::string fileName, int hands);
;
Table::Table(int decks, int _balance)
: shoe(decks), balance(_balance), blackjackPayoff(1.5), hitSoft17(true), bet(10)
bool Table::isCurrentGame()
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
if(it->active)
return true;
return false;
void Table::deal()
dealer.clear();
player.clear();
dealer.addCard( shoe.pullCard(true) );
dealer.addCard( shoe.pullCard() );
player.push_back(Hand());
player[0].addCard( shoe.pullCard() );
player[0].addCard( shoe.pullCard() );
if(player[0].getHandValue() == 21 && dealer.getHandValue() == 21)
player[0].active = false;
else if(player[0].getHandValue() == 21)
player[0].active = false;
else if(dealer.getHandValue() == 21)
player[0].active = false;
void Table::hit(int split)
player[split].hand.push_back( shoe.pullCard() ); //SEGFAULT HERE
if(player[split].getHandValue() > 21)
player[split].active = false;
void Table::split(int split)
player.push_back(Hand());
player[player.size() - 1].hand.push_back( player[split].split() );
player[split].hand.push_back( shoe.pullCard() );
player[player.size() - 1].hand.push_back( shoe.pullCard() );
if(player[split].getHandValue() == 21)
player[split].active = false;
else if(player[player.size() - 1].getHandValue() == 21)
player[player.size() - 1].active = false;
double Table::stand()
double winnings(0.0);
bool allNats(true);
//dealer.push_back( shoe.pullCard() );
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
if(it->cards() == 2 && it->getHandValue() == 21)
winnings += bet * blackjackPayoff;
it->isBlackjack = true;
else
allNats = false;
if(it->getHandValue() > 21)
it->busted = true;
if(!allNats)
while(dealer.getHandValue() <= 17)
if(dealer.getHandValue() == 17)
//dealer has 17 and doesnt hit soft 17s so hes not going to draw anymore cards
if( !hitSoft17 || dealer.cards() != 2 || !(dealer.hand.at(0) == ACE || dealer.hand.at(1) == ACE) )
break;
dealer.addCard( shoe.pullCard() );
for(std::vector<Hand>::iterator it = player.begin(); it != player.end(); ++it)
if(!it->isBlackjack)
if(it->busted)
if(it->doubled)
winnings -= 2.0 * bet;
else
winnings -= bet;
else if(dealer.getHandValue() > 21 || dealer.getHandValue() < it->getHandValue())
if(it->doubled)
winnings += 2.0 * bet;
else
winnings += bet;
else if(dealer.getHandValue() > it->getHandValue())
if(it->doubled)
winnings -= 2.0 * bet;
else
winnings -= bet;
//only other scenario is a push which we dont do anythign for
return winnings;
void Table::simulate(std::string fileName, int hands)
int i(0), countHL;
double trueCountHL;
std::ofstream ofs(fileName);
Action action;
while(i < hands)
deal();
VisibleCards vc(player[0].at(0), player[0].at(1), dealer.at(0));
while(isCurrentGame())
int j(0), q(1);
countHL = shoe.getCountHL();
trueCountHL = shoe.getTrueCountHL();
for(int l = 0; l < q; ++l)
while(player[l].active)
if(player[l].cards() == 2)
action = getBasicStrategy(player[l].getHandValue(), dealer.at(0).getCardValue(),
player[l].at(0).getCardValue(), player[l].at(1).getCardValue());
else
action = getBasicStrategy(player[l].getHandValue(), dealer.at(0).getCardValue());
switch(action)
case HIT:
hit(j);
break;
case DOUBLE:
hit(j);
if(player[l].cards() == 3)
player[l].doubled = true;
player[l].active = false;
break;
case SPLIT:
if(player.size() <= 4)
split(j);
++q;
else
hit(j);
break;
case STAND:
player[l].active = false;
break;
++j;
double winnings = stand();
balance += winnings;
ofs << std::endl << std::fixed << vc << "," << winnings << "," << std::setprecision(2) << trueCountHL
<< "," << balance << "," << std::setprecision(0) << countHL << "," << shoe.getRemainingDecks();
ofs << std::endl << 1;
//BlackjackData bjd(winnings, balance, shoe.getTrueCountHL(), shoe.getCountHL(), HIT);
//strat.addData(vc, bjd);
++i;
strat.print(fileName);
【问题讨论】:
一个完整的程序,其输入可以证明问题是理想的。 【参考方案1】:看起来您正在尝试使用 hand[0]
和 hand.erase(hand.begin())
从 hand
获取第一张卡片,而没有先检查是否有第一张卡片。如果hand
为空(就像从构造函数中新创建的Hand
一样),这会导致未定义的行为,这很可能会在以后表现为崩溃。
【讨论】:
这绝对是我需要解决的一个潜在问题,但似乎不是这里的问题,我尝试检查手是否都是空的,但事实并非如此。此外,我在 MSVS 中进行了调试,似乎有一个有效的卡片对象(具有等级和花色)试图在崩溃前被推回向量中。【参考方案2】:我盯着这个看了一天,想不通,走出去,意识到我有一个旧变量“j”,当我调用“hit”时,我用它来访问向量而不是“l” "函数....感谢大家的帮助。
【讨论】:
以上是关于std::vector push_back 上的 Segfault/“向量不可解引用”的主要内容,如果未能解决你的问题,请参考以下文章
std::vector.push_back() 的奇怪(记忆?)问题
没有匹配函数调用‘std::vector::push_back(std::string&)’
正确使用用户定义类型的 std::vector.push_back()