C++ array is not empty where it should be

匿名 (未验证) 提交于 2019-12-03 01:09:02

问题:

I'm trying to write a hash map with a dynamic array that stores a set of pointers to a linked list struct. I've been running into some strange memory issues. It seems like there are pointers in my array that shouldn't be.

I get an error where even though the index that should be generated from the single insert I'm doing is 16, as I loop through the array, there are some non-zero items:

start  16 //(output of index from insert) dumbtest //(get of nonexistent key) 0 // result of get of non-existent key HashTable:     0   0x0--     0x0      1   0x0--     0x0      2   0xeb-- //Why is this not 0x0?           0xeb 

I end up with an error: Thread 1: EXC_BAD_ACCESS (code=1, address=0x80000002c)

from this line in the string library:

 _LIBCPP_INLINE_VISIBILITY     bool __is_long() const _NOEXCEPT         {return bool(__r_.first().__s.__size_ & __short_mask);} 

I'm guessing that's the result of treating the junk in the array as a pointer and then trying to cast random bytes as the string of the "key" property.

Here is the class file

#include "hashtable.hpp" using namespace std;  HashTable::HashTable() {     this->length = 32;     this->buck = new LinkedList *[32]; };   unsigned int HashTable::hash(string key) {     int hash = 7;     for (int i = 0; i < key.length(); i++) {         hash = hash*31 * key[i];     }     hash = hash % this->length;     return std::abs(hash); }  int HashTable::find(string key) {     int index = this->hash(key);     LinkedList *curr = this->buck[index];     while(curr != nullptr)     {         if(curr->key == key)         { //            std::cout << curr;             int val = curr->value;             return val;         }          curr = curr->next;     }     return 0; }   void HashTable::output() {     cout << "\nHashTable:\n";     for(int i = 0; i < this->length; i++)     {         LinkedList *curr = this->buck[i];         cout << "\t";         cout << i;         cout << "\t";         cout << curr;         cout << "--\n\t";         while (curr != nullptr){             cout << "\t";             cout << curr;             cout << ":";             cout << curr->key;             cout << ",";             cout << curr->value;             cout << ",";             cout << curr->next;             curr = curr->next;         }         cout << this->buck[i];         cout << "\n";         cout << "\n";     } }  void HashTable::insert(string key, int value) {     unsigned int index = this->hash(key);     cout << index;     LinkedList *curr = this->buck[index];     LinkedList *ins = new LinkedList{         key,         value,         NULL,     };     if (curr == nullptr){         this->buck[index] = ins;     }     else     {         while(curr->next != nullptr)         {             curr = curr->next;         }          curr->next = ins;     } }    void HashTable::rehash() {     this->length = 2 * this->length;     LinkedList** old = this->buck;     this->buck = new LinkedList* [this->length];     for (int i=0; i < this->length; i++)     {         LinkedList* curr = old[i];         while(curr != nullptr)         {             this->insert(curr->key, curr->value);             curr = curr->next;         }     } } 

And then my header

#ifndef hashtable_hpp #define hashtable_hpp  #include <stdio.h> #include <string> #include <iostream>   struct LinkedList {     std::string key;     int value;     LinkedList *next; };   class HashTable { private:     int length;     LinkedList** buck;     unsigned int hash(std::string key);     void rehash();  public:     HashTable();     int find(std::string key);     void insert(std::string key, int value);     bool remove(std::string key);     void output();  }; #endif /* hashtable_hpp */ 

Here is the main file running it:

#include <stdio.h> #include <string> #include <iostream> #include "hashtable/hashtable.hpp"  int main(int argc, const char * argv[]) {     std::cout << "start\n";      HashTable ht;     ht.insert("test", 3); //    ht.output();     std::cout << "\ndumbtest\n";     int dumbval = ht.find("testy");     std::cout << dumbval;     ht.output();      std::cout << "\ntest\n";     int val = ht.find("test");     std::cout << val;      std::cout << "\nend";     return 0; } 

Here's the stack trace:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x80000002c)   * frame #0: 0x00000001000021bd algStudy`std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) [inlined] std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__is_long(this="") const at string:1221     frame #1: 0x00000001000021bd algStudy`std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) [inlined] std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::__get_pointer(this="") const at string:1315     frame #2: 0x00000001000021bd algStudy`std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) [inlined] std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >::data(this="") const at string:1129     frame #3: 0x00000001000021bd algStudy`std::__1::basic_ostream<char, std::__1::char_traits<char> >& std::__1::operator<<<char, std::__1::char_traits<char>, std::__1::allocator<char> >(__os=0x00007fff9b480660, __str="") at ostream:1047     frame #4: 0x0000000100002067 algStudy`HashTable::output(this=0x00007ffeefbff4c8) at hashtable.cpp:63     frame #5: 0x00000001000014c5 algStudy`main(argc=1, argv=0x00007ffeefbff5e8) at main.cpp:23     frame #6: 0x00007fff6388d015 libdyld.dylib`start + 1     frame #7: 0x00007fff6388d015 libdyld.dylib`start + 1 

Any ideas?

回答1:

From your code, I can tell you allocate the linked list from the heap, which means you cannot guarantee the Operating System helps you clear the allocated memory.

Realistically, nullptr means that it simply points to address NULL (zero) which you can not to read/write to it, so that pointer is "null".

There is a C language solution better than loop and setting to nullptr: Add this single line after you allocated HashTable::buck

memset(buck,0,sizeof(buck)); 

This line sets the bytes in the space of HashTable::buck to zero.



标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!