Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Exception thrown when inserting into a map

When I try to insert an object into my map, it throws the following exception:

Unhandled exception at 0x77a015de in Main.exe: 0xC0000005: Access violation reading location 0x00000004.

The "reading location 0x00000004" makes me think it's some sort of null pointer exception. However, the map itself is a static map, initialized in the .cpp file. Why wouldn't it have a location when trying to do the insert?

Here's the class. It's a player class that manages mapping IDs to players:

// Player.hpp
class Player {
  public:

    Player(){}; // I had to make this public, otherwise it wouldn't compile.
    Player(Player &p);
    Player & operator=(const Player &p);
    bool operator==(const Player &p);

    int getID() const;
    int getTeam() const;
    string getName() const;
    Vec3 getColor() const;

    static Player newPlayer(int team, string name, Vec3 color);

  private:
    Player(int id, int team, string name, Vec3 color);
    int id,
        team;
    string name;
    Vec3 color;

    static std::map<int, Player> players;
};

and the cpp file:

#include "Player.hpp"
std::map<int, Player> Player :: players;
int Player :: currentPlayer=-1;

// Constructor
Player :: Player(Player &p) : id(p.getID()),
                              team(p.getTeam()),
                              name(p.getName()),
                              color(p.getColor()){}

Player & Player :: operator=(const Player &p){
  if (this==&p){
    return *this;
  }

  id=p.getID();
  team=p.getTeam();
  name=p.getName();
  color=p.getColor();

  return *this;
}

bool Player :: operator==(const Player &p){
  return p.getID()==getID();
}

// Factory
Player Player :: newPlayer(int team,
                           string name,
                           Vec3 color){
  int playerID=0;
  if (players.size()>0){
    int playerID=(*players.rbegin()).first+1; // get an ID higher than the largest already there.
  }

  Player p(playerID, team, name, color);
  players.insert(std::make_pair(playerID, p)); // EXCEPTION THROWN HERE
  return players[playerID];
}

// Internal Constructor
Player :: Player(int id,
                 int team,
                 string name,
                 Vec3 color) : id(id),
                               team(team),
                               name(name),
                               color(color){}

Can anyone help me understand what's going on here?

EDIT: The code that's calling this method is in main.hpp, outside of any methods, in the global scope:

Player player1=Player::newPlayer(1, "p1", Vec3(0.2, 0.2, 0.8)),
       player2=Player::newPlayer(2, "p2", Vec3(0.8, 0.2, 0.2));
like image 653
whiterook6 Avatar asked Jul 17 '26 10:07

whiterook6


2 Answers

To address the need for a public default constructor, try changing this:

Player p(playerID, team, name, color);
players.insert(std::make_pair(playerID, p)); // EXCEPTION THROWN HERE
return players[playerID];

into this:

return players.insert(std::make_pair(playerID, Player(playerID, team, name, color))).first->second;

(Explanation: The []-operator requires that your mapped type be default-constructible. Using it means that you're ignoring the knowledge that the key that you're looking up exists in the map. The operator wants to create a new default-constructed element if the key that you give it doesn't exist.)


Update: You also have to address the static initialization problem. Here's one way how to do this:

// header:

class Player {
public:
    static std::map<int, Player> & players();
    // ...
};

// implementation:

std::map<int, Player> & Player::players()
{
    static std::map<int, Player> impl;
    return impl;
}

Now just use Player::players() to get a reference to the map.

like image 132
Kerrek SB Avatar answered Jul 19 '26 01:07

Kerrek SB


Is the insertion also happening as part of the static initialisation of some other object?

If so you've hit a classic C++ gotcha: the order of static initialisation between different files is largely undefined, and rarely does what you want.

like image 26
Alan Stokes Avatar answered Jul 18 '26 23:07

Alan Stokes



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!