mardi 30 mai 2023

Trouble printing a re-hashed table

I'm working on my Hash Table assignment and I ran into an issue when printing the new table after re-hashing all the values. The compiler reports this error:

terminate called after throwing an instance of 'std::logic_error'
  what():  basic_string::_M_construct null not valid
Aborted (core dumped)

Now there are a lot of questions on SO about this, but none of them seemed to answer my question. It was mostly people assigning a non-string value to a std::string.

I am reading my original data from a .csv file and I am supposed to store them in a Hash Table and print them. When I fetch the data for the first time I can print them just fine, but after re-hashing the error I listed above gets thrown.

I tried producing a minimal reproducible example but if I decrease the input size(from 250K to 3 inputs) re-hashing seems to work just fine and no error gets raised.

Am I doing something completely wrong? Could my data be corrupted? Am I dealing with a massive pointer ownership problem (I have to use raw pointers)?

I know I pasted a lot fo code and I am very far from a minimal reproducible example, but I couldn't find a different way to ask a bout this.

When using gdb to debug the code (after rehashing) it stops and terminates when it hits the

std::cout << entry << std::endl;

void CovidDB::rehash()

void CovidDB::rehash() {
  auto is_prime = [](int num) {
    if (num <= 1)
      return false;

    for (int i = 2; i <= std::sqrt(num); ++i) {
      if (num % i == 0)
        return false;
    }
    return true;
  };

  auto find_next_prime = [&is_prime](int num) {
    while (true) {
      if (is_prime(num))
        return num;
      ++num;
    }
  };

  int new_size = size * 2;
  int new_prime_size = find_next_prime(new_size);

  CovidDB new_table(new_prime_size);

  for (auto row : HashTable) {
    for (auto entry : row) {
      if (entry != nullptr) {
        new_table.add(entry);
      }
    }
  }

  HashTable = new_table.HashTable;
  size = new_prime_size;

#ifdef LOG
  std::cout << "\n[LOG]: Rehashed, new table size: " << size << std::endl;
  try {
    if (new_table.size != size) {
      throw std::logic_error("\n[size mismatch!]");
    }
  }
  catch (std::exception& error) {
    std::cerr << "[Error]:\t" << error.what() << std::endl;
  }
#endif //LOG
  return;
}

bool CovidDB::add(DataEntry* entry)

bool CovidDB::add(DataEntry* entry) {
  int index = hash(entry->get_country());
  bool added = false;

  if (HashTable[index].empty()) {
    HashTable[index].push_back(entry);
  }
  else {
    for (DataEntry* existing_entry : HashTable[index]) {
      std::atomic<bool> valid(false);
      valid.store(
        hash(existing_entry->get_country()) == hash(entry->get_country()) &&
        existing_entry->get_country() == entry->get_country()
      );
      if (valid && entry != nullptr) {
        existing_entry->set_date(entry->get_date());
        existing_entry->set_c_cases(existing_entry->get_c_cases() + entry->get_c_cases());
        existing_entry->set_c_deaths(existing_entry->get_c_deaths() + entry->get_c_deaths());
        added = true;
        //delete entry;
        break;
      }
    }
    if (!added) {
      HashTable[index].push_back(entry);
    }
  }

  return added;
}

void CovidDB::display_table()

void CovidDB::display_table() {
  bool is_empty = true;

  for (const auto& vec : HashTable) { //if 1st dimension is empty
    if (!vec.empty()) {
      is_empty = false;
      break;
    }
  }

  try {
    if (is_empty) {
      throw std::logic_error("\n[Data Base is empty]\n");
      return;
    }
  }
  catch (std::exception& error) {
    std::cerr << "[Error]:\t" << error.what() << std::endl;
    return;
  }

  for (auto vec : HashTable) {
    for (auto entry : vec) {
      if (entry != nullptr) {
        std::cout << entry << std::endl;
        sleep(50);
      }
    }
  }
  }
  std::cout << std::endl;
  return;
}

overloaded ostream operator

  inline static void print_data_entry(std::ostream& stream, DataEntry* entry) {
    char const SPACE = ' ';
    if (entry != nullptr) {
      stream << "[Date: " << entry->get_date() << "]," << SPACE
        << "[Country: " << entry->get_country() << "]," << SPACE
        << "[Cases: " << entry->get_c_cases() << "]," << SPACE
        << "[Deaths: " << entry->get_c_deaths() << "]";
    }
  }

  inline friend std::ostream& operator<<(std::ostream& stream, DataEntry* entry) {
    print_data_entry(stream, entry);
    return stream;
  }

Aucun commentaire:

Enregistrer un commentaire