I'm trying to callback using a pointer to a base type, but something along the way is giving me a HeapValidation error.
But I have no idea where it's messing up. What the hell am I not doing correctly?
Allow me to explain...
This is the "Event" base structure, which just contains an integer "code" to discern which event type it is.
1 2 3 4 5 6 7
|
struct Event {
static const char Leave = 1;
int code = 0;
Event(int code) : code(code) { }
virtual ~Event() { }
};
|
This is the "Leave" event, which extends Event and contains "Player" object...
1 2 3 4 5 6
|
struct Leave : Event {
Player player;
Leave(Player p) : Event(Event::Leave), player(p) { }
~Leave() { }
};
|
These are the globals, to make this more readable I just took the "players" map and relevant methods from the "World" class.
1 2
|
std::map<uint32_t, Player> players;
bool(__cdecl* callback)(game::Event*) = nullptr;
|
These are the relevant methods from "World"
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
|
// ID is a macro for "id + 1"
Player & make_player(uint32_t id) {
players[ID] = Player(ID, "");
return players[ID];
}
Player & make_player() {
return make_player(0);
}
Player & find_player(uint32_t id) {
if (players.find(ID) == players.end())
return make_player(ID);
return player;
}
|
This may require more explanation, so feel free to ask. The following two methods are to get a reference of the player in the "players" map. It performs a macro called "PARAM_CHECK" which is just to see if the "Parameters" map (uint8_t key, Value* value) contains the key "i" and if that Value* is of the correct type code. If the parameters map does not contain the value, it will just return 0, so we reference the 0th key of the "players" map, like above. Otherwise, we return a reference to the player in the players map.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
|
// uint32_t template specialization
template<>
uint32_t get_num(Parameters* params, int i) {
if (!PARAM_CHECK(i, TypeCode::Integer))
return 0;
// big_endian <- &ptr <- TypedValue* <- Value*
TypedValue* val = (TypedValue*)(*params)[i];
return htonl(*((uint32_t*)&val->ptr));
}
Player& get_player(Parameters* params, int i) {
if (!PARAM_CHECK(i, TypeCode::Integer))
return make_player(); // default to possible saved data we have
uint32_t id = get_num<uint32_t>(params, i);
return find_player(id);
}
|
Finally, we have these two methods, which are to discern the type of the event (code), and create the Event object (Leave in the first case), then pass it to dispatch to perform the callback. I originally intended for this to be an async call so it wouldn't block, but I keep getting this damn HeapValidation error, so I'm simplifying it for now.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
void dispatch(Event& event) {
callback(&event);
}
bool _dispatch_event(uint16_t code, Parameters* params) {
Player& source = get_player(params, 0);
switch (code) {
case MessageCode::Events::Leave: {
print("Leave Dispatched.");
Leave event(source);
dispatch(static_cast<Event&>(event));
break;
}
...
}
}
|
That should be all the code necessary, feel free to ask if you need more information. The problem is that I don't know, necessarily, what a HeapValidation error is. I assume it's because I'm making a call to callback and the heap is not the correct size or maybe it's a different address than was intended, and that's what is throwing the error, but I genuinely have no clue.