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