Home > Software engineering >  segfault with self-declared hash function
segfault with self-declared hash function

Time:06-06

ChunkCorner.h

#pragma once
#include <filesystem>

#include <iostream>

class ChunkCorner
{
public:
    int x;
    int y;
    std::filesystem::path to_filename();
};

size_t hf(const ChunkCorner &chunk_corner);

bool eq(const ChunkCorner &c1, const ChunkCorner &c2);

ChunkCorner.cpp: fwiw: The hf and eq function implementation is based on the C Book p. 917.

#include "ChunkCorner.h"

using namespace std;

size_t hf(const ChunkCorner &chunk_corner)
{
    return hash<int>()(chunk_corner.x) ^ hash<int>()(chunk_corner.y);
}

bool eq(const ChunkCorner &c1, const ChunkCorner &c2)
{
    return c1.x == c2.x && c1.y == c2.y;
}

[...]

In another bit of code I use the class as follows:

unordered_set<ChunkCorner, decltype(&hf), decltype(&eq)> chunks_to_load {};

ChunkCorner c {1,2};
chunks_to_load.insert(c);

On the insert call I get a segfault (determined using breakpoints).

I use VS Code and when I launch the program in debug mode, it jumps to the following bit on segfault in hashtable_policy.h:

      __hash_code
      _M_hash_code(const _Key& __k) const
      {
    static_assert(__is_invocable<const _H1&, const _Key&>{},
        "hash function must be invocable with an argument of key type");
    return _M_h1()(__k);
      }

I am new to C and have trouble understanding what the issue is and I am not sure how to proceed debugging...

CodePudding user response:

You need to pass the hash and equals functions to your constructor. You've declared their type in the type arguments, which is going to be a pointer to function, but you haven't passed them in. So they're likely being zero initalized, so nullptr. Using them correctly should be done like this:

unordered_set<ChunkCorner, decltype(&hf), decltype(&eq)> chunks_to_load {16, hf, eq};

However, what I recommend is rewrite your Hash/Equals functions into function objects. This way, the default operations will work properly.

struct MyHasher {
  size_t operator()(const ChunkCorner &chunk_corner) const
   {
     return hash<int>()(chunk_corner.x) ^ hash<int>()(chunk_corner.y);
   }
};

struct MyEq {
 bool operator()(const ChunkCorner &c1, const ChunkCorner &c2) const
  {
    return c1.x == c2.x && c1.y == c2.y;
  }
};
  • Related