Home > Net >  C unordered set of custom class - segfault on insert
C unordered set of custom class - segfault on insert

Time:12-03

I am following a tutorial on creating a hexagon map for a game. The source has it in struct, but I want it to be a class and so far I am unable to make it work. It compiles fine, but when I try to insert a new value in it, it segfaults. I am probably doing the hash function wrong, or something, but I have ran out of ideas on fixing it. Thanks!

main.c

#include <unordered_set>
#include "hexagonField.hpp"

int main(int argc, char **argv)
{
    std::unordered_set <HexagonField> map;
    map.insert(HexagonField(0, 0, 0));
            
    return 0;
}

hexagonField.hpp

#ifndef HEXAGON_H
#define HEXAGON_H
#include <assert.h>
#include <vector>

class HexagonField
{
public:
    const int q, r, s;
    HexagonField(int q, int r, int s);
    ~HexagonField();
    HexagonField hexagonAdd(HexagonField a, HexagonField b);
    HexagonField hexagonSubtract(HexagonField a, HexagonField b);
    HexagonField hexagonMultiply(HexagonField a, int k);
    int hexagonLength(HexagonField hex);
    int hexagonDistance(HexagonField a, HexagonField b);
    HexagonField hexagonDirection(int direction /* 0 to 5 */);
    HexagonField hexagonNeighbor(HexagonField hex, int direction);

    const std::vector<HexagonField> hexagonDirections = {
    HexagonField(1, 0, -1), HexagonField(1, -1, 0), HexagonField(0, -1, 1),
    HexagonField(-1, 0, 1), HexagonField(-1, 1, 0), HexagonField(0, 1, -1)
    };

    bool operator == (const HexagonField comparedHex) const
    {
        return this->q == comparedHex.q && this->r == comparedHex.r && this->s == comparedHex.s;
    }
    bool operator != (const HexagonField comparedHex) const
    {
        return !(*this == comparedHex);
    };
};

namespace std
{
  template<>
    struct hash<HexagonField>
    {
      size_t operator()(const HexagonField & obj) const
      {
        return hash<int>()(obj.q);
      }
    };
}
#endif

hexagonField.cpp

#include "hexagonField.hpp"

HexagonField::HexagonField(int q, int r, int s): q(q), r(r), s(s)
{
    assert (q   r   s == 0);
}

HexagonField HexagonField::hexagonAdd(HexagonField a, HexagonField b)
{
    return HexagonField(a.q   b.q, a.r   b.r, a.s   b.s);
}

HexagonField HexagonField::hexagonSubtract(HexagonField a, HexagonField b)
{
    return HexagonField(a.q - b.q, a.r - b.r, a.s - b.s);
}

HexagonField HexagonField::hexagonMultiply(HexagonField a, int k)
{
    return HexagonField(a.q * k, a.r * k, a.s * k);
}

int HexagonField::hexagonLength(HexagonField hex) {
    return int((abs(hex.q)   abs(hex.r)   abs(hex.s)) / 2);
}

int HexagonField::hexagonDistance(HexagonField a, HexagonField b) {
    return hexagonLength( hexagonSubtract(a, b));
}

HexagonField HexagonField::hexagonDirection(int direction /* 0 to 5 */) {
    assert (0 <= direction && direction < 6);
    return hexagonDirections[direction];
}

HexagonField HexagonField::hexagonNeighbor(HexagonField hex, int direction) {
    return hexagonAdd(hex, hexagonDirection(direction));
}

CodePudding user response:

If you run your program under a debugger, you will see it actually overflowed the stack while trying to construct HexagonField objects. This is because every object has a vector of 6 more HexagonField objects, which in turn needs another vector, and so on.

As a quick fix, you can take hexagonDirections out of the HexagonField class and move it to a static file-scoped variable at the top of HexagonField.cpp instead:

static const std::vector<HexagonField> hexagonDirections = {
HexagonField(1, 0, -1), HexagonField(1, -1, 0), HexagonField(0, -1, 1),
HexagonField(-1, 0, 1), HexagonField(-1, 1, 0), HexagonField(0, 1, -1)
};

Alternatively, you can leave hexagonDirections as a static class member and move the definition to your .cpp file:

// HexagonField.h
class HexagonField {
  ...
  static const std::vector<HexagonField> hexagonDirections;
  ...
};
// HexagonField.cpp
const std::vector<HexagonField> HexagonField::hexagonDirections = {
  HexagonField(1, 0, -1), HexagonField(1, -1, 0), HexagonField(0, -1, 1),
  HexagonField(-1, 0, 1), HexagonField(-1, 1, 0), HexagonField(0, 1, -1)
};
  • Related