Как предотвратить повторную инициализацию Google Hash

0

Я пытаюсь внедрить Google Dense Hash. Это первый раз, когда я использую C++ для чего-то более сложного, чем простые векторы с целыми числами, поэтому я не могу найти проблему, хотя я думаю, что она должна быть простой.

Я вставил соответствующий код ниже.

header.h:

#ifndef HEADER_H
#define HEADER_H

//#include <stdint.h>
#include <iostream>
#include <vector>
#include <ctime>
#include <fstream>
#include <boost/random.hpp>
#include <sparsehash/dense_hash_map>

#include "gene.h"
#include "genome.h"
#include "markovgraph.h"

//Debugger
#define DEBUG false
#define STATES false
#define MANUAL false

//Setting up the randomness
typedef boost::mt19937 RandomNumberGenerator;
typedef boost::uniform_int<> NumberDistribution;
typedef boost::variate_generator<RandomNumberGenerator&, NumberDistribution> Generator;

static RandomNumberGenerator generator;

#endif

traverse-markov.cc:

//Include the header
#include "header.h"

int main (int argc, char* argv[]) {

    //Default values of Controlvariables
    int initial_conditions = 100000; // Number of initial states to generate.
    int repeat_per_condition = 1; // Default number of initial states to generate.
    int iterations = 2000; // Number of steps to run.
    int seed = 1234; // Random seed to generate conditions
    bool synchronous = true;
    bool random_order = false;
    bool silent = false;
    bool false_feedback = false;
    bool same_states = false;
    int decay_counter = 0;
    int update_method = 0;
    std::string input_filename;
    std::string output_filename;
    std::string initial_condition_file;

    Markovgraph markov;
    markov.add_vertex("a");
    markov.add_vertex("a");
    markov.add_vertex("b");
    markov.add_vertex("c");

    markov.vertices_status();
    std::cout << "Number of vertices: " << markov.vertex_count() << std::endl;
    return 0;
}

markovgraph.h:

#ifndef MARKOVGRAPH_H
#define MARKOVGRAPH_H

extern uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed );


// simple hash adapter for types without pointers
template<typename T>
struct MurmurHasher {
    size_t operator()(const T& t) const {
        return MurmurHash64A(&t, sizeof(t), 0);
    }    
};

// specialization for strings
template<>
struct MurmurHasher<std::string> {
    size_t operator()(const std::string& t) const {
        return MurmurHash64A(t.c_str(), t.size(), 0);
    }    
};

struct eqstr
{
  bool operator()(const char* s1, const char* s2) const
  {
    return (s1 == s2) || (s1 && s2 && (strcmp(s1, s2) == 0));
  }
};

typedef google::dense_hash_map<const char*, long int, MurmurHasher<const char*>, eqstr> dense_hash_t;

class Markovgraph {
    //Private variables
  dense_hash_t vertices;
  //google::dense_hash_map<const char*, long, MurmurHasher<const char*>, eqstr> edges;

    public:
        //Public variables

        //Functions
        Markovgraph(); //Constructor
    void add_vertex(std::string vertex);
    void print_vertex(std::string vertex);
    void vertices_status();
    int vertex_count();
    //add_edge(std::string upvertex,std::string downvertex);
    ~Markovgraph(); //Destructor
};

#endif

markovgraph.cc:

//Include the header
#include "header.h"

// 64-bit hash for 64-bit platforms
// copied from https://sites.google.com/site/murmurhash/
uint64_t MurmurHash64A ( const void * key, int len, unsigned int seed ) {
  const uint64_t m = 0xc6a4a7935bd1e995;
  const int r = 47;

  uint64_t h = seed ^ (len * m);

  const uint64_t * data = (const uint64_t *)key;
  const uint64_t * end = data + (len/8);

  while(data != end)
  {
    uint64_t k = *data++;

    k *= m; 
    k ^= k >> r; 
    k *= m; 

    h ^= k;
    h *= m; 
  }

  const unsigned char * data2 = (const unsigned char*)data;

  switch(len & 7)
  {
  case 7: h ^= uint64_t(data2[6]) << 48;
  case 6: h ^= uint64_t(data2[5]) << 40;
  case 5: h ^= uint64_t(data2[4]) << 32;
  case 4: h ^= uint64_t(data2[3]) << 24;
  case 3: h ^= uint64_t(data2[2]) << 16;
  case 2: h ^= uint64_t(data2[1]) << 8;
  case 1: h ^= uint64_t(data2[0]);
          h *= m;
  };

  h ^= h >> r;
  h *= m;
  h ^= h >> r;

  return h;
} 

//Constructor
Markovgraph::Markovgraph() {
    vertices.set_empty_key(NULL);
    //edges.set_empty_key(NULL);
}

//Add vertex function
void Markovgraph::add_vertex(std::string vertex) {
  vertices[vertex.c_str()] = 1;
}

//Print vertex function
void Markovgraph::print_vertex(std::string vertex) {
  std::cout << vertex << " --> " << vertices[vertex.c_str()] << std::endl;
}

//Print all vertices
void Markovgraph::vertices_status() {
  // Print whole hash table to cout
  for(dense_hash_t::const_iterator it = vertices.begin(); it != vertices.end(); it++){
    std::cout << it->first << " --> " << it->second << std::endl;
  }
}

//Vertex count
int Markovgraph::vertex_count() {
  return vertices.size();
}



//Destructor
Markovgraph::~Markovgraph() {
    //Destroy things...
}

Выход:

c --> 1
Number of vertices: 1

Так что как-то сохраняется только последняя "вершина". Ранние пары ключ/значение, которые я пытался добавить с помощью markov.add_vertex(), исчезли.

Надеюсь, ты поможешь мне, потому что я проработал больше недели.

Теги:
hashmap
variable-assignment

1 ответ

0
void Markovgraph::add_vertex(std::string vertex) {
  vertices[vertex.c_str()] = 1;
}

приведет к тому, что указатель на строку local add_vertex, и как только вы покинете эту функцию, vertex перестанет существовать, и, таким образом, с помощью указателя будет UB.

Вероятно, самый простой способ исправить это - сделать ваш ключ std::string

  • 0
    Хорошо, я попробую это.
  • 0
    Хорошо, я не уверен, что вы можете помочь мне в дальнейшем, но когда я заменяю const char* на std::string , я получаю: libc++abi.dylib: terminate called throwing an exception". с помощью GDB дает мне std::basic_string<char, std::char_traits<char>, std::allocator<char> >::basic_string () и std::string::_S_construct<char const*> () .

Ещё вопросы

Сообщество Overcoder
Наверх
Меню