On Fri, Nov 11, 2016 at 10:30 PM, nick <[email protected]> wrote:
> Greetings Gcc Folks,
> Either this is me doing something very simple in a school assignment for
> creating a basic hashtable
> or a compiler bug. I am currently seeing this error during my tables run on
> copy constructor call during
> the tester and have set to find out why it doesn't work. After some googling
> it seems either I am doing
> string pointer to string swaps.
This should have gone to gcc-help@ rather than here. This mailing
list is more for the automated emails from bugzilla.
Anyways I think the problem is you assume:
new Record*[N];
Will NULL out the array. It does not.
Thanks,
Andrew
> or it's a compiler bug. This is the error I am getting after running in gdb
> with backtrace:
> Program received signal SIGSEGV, Segmentation fault.
> 0x00007ffff7b769bb in std::__cxx11::basic_string<char,
> std::char_traits<char>, std::allocator<char>
> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>,
> std::allocator<char> > const&) ()
> from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
> (gdb) backtrace
> #0 0x00007ffff7b769bb in std::__cxx11::basic_string<char,
> std::char_traits<char>, std::allocator<char>
> >::basic_string(std::__cxx11::basic_string<char, std::char_traits<char>,
> std::allocator<char> > const&) ()
> from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
> #1 0x00000000004067f6 in HashTable<int>::Record::getKey() const ()
> #2 0x00000000004060ee in HashTable<int>::HashTable(HashTable<int> const&) ()
> #3 0x0000000000403cab in main ()
> This is the complete code for the project:
> #include <string>
> #include <utility>
> #include<iostream>
> using namespace std;
> /*The functions I updated for Simple Table are
> 1.search
> 2.grow
> 3.update
> 4.Both Copy Constructor and Copy Assignment
> 5.Destructor
> */
> template <class TYPE>
> class Table {
> public:
> Table() {}
> virtual bool update(const string& key, const TYPE& value) = 0;
> virtual bool remove(const string& key) = 0;
> virtual bool find(const string& key, TYPE& value) = 0;
> virtual ~Table() {}
> };
>
> template <class TYPE>
> class SimpleTable :public Table<TYPE> {
>
> struct Record {
> TYPE data_;
> string key_;
> Record(const string& key, const TYPE& data) {
> key_ = key;
> data_ = data;
> }
>
> };
>
> Record** records_; //the table
> int max_; //capacity of the array
> int size_; //current number of records held
> int search(const string& key);
> void sort();
> void grow();
> public:
> SimpleTable(int maxExpected);
> SimpleTable(const SimpleTable& other);
> SimpleTable(SimpleTable&& other);
> virtual int numRecords();
> virtual bool isEmpty();
> virtual bool update(const string& key, const TYPE& value);
> virtual bool remove(const string& key);
> virtual bool find(const string& key, TYPE& value);
> virtual const SimpleTable& operator=(const SimpleTable& other);
> virtual const SimpleTable& operator=(SimpleTable&& other);
> virtual ~SimpleTable();
> };
>
>
> //returns index of where key is found.
> template <class TYPE>
> int SimpleTable<TYPE>::search(const string& key) {
> int rc = -1;
> for (int i = 0; i<size_; i++) {
> if (records_[i]->key_ == key) {
> rc = i;
> break;
> }
> }
> return rc;
> }
> //checks if array is empty
> template <class TYPE>
> bool SimpleTable<TYPE>::isEmpty(){
> return size_==0;
> }
> template <class TYPE>
> //return size of array
> int SimpleTable<TYPE>::numRecords(){
> return size_;
> }
> //sort the according to key in table
> template <class TYPE>
> void SimpleTable<TYPE>::sort() {
> int minIdx = 0;
> for (int i = 0; i<size_; i++) {
> minIdx = i;
> for (int j = i + 1; j<size_; j++) {
> if (records_[j]->key_ < records_[minIdx]->key_) {
> minIdx = j;
> }
> }
> Record* tmp = records_[i];
> records_[i] = records_[minIdx];
> records_[minIdx] = tmp;
> }
> }
>
> //grow the array by one element
> template <class TYPE>
> void SimpleTable<TYPE>::grow() {
> Record** newArray = new Record*[max_ + 1];
> max_ = max_ + 1;
> for (int i = 0; i<size_; i++) {
> newArray[i] = records_[i];
> }
> records_ = std::move(newArray);
> }
>
> /* none of the code in the function definitions below are correct. You can
> replace what you need
> */
> template <class TYPE>
> SimpleTable<TYPE>::SimpleTable(int maxExpected) : Table<TYPE>() {
> records_ = new Record*[maxExpected];
> max_ = maxExpected;
> size_ = 0;
> }
>
> template <class TYPE>
> SimpleTable<TYPE>::SimpleTable(const SimpleTable<TYPE>& other) {
> records_ = new Record*[other.max_];
> max_ = other.max_;
> size_ = 0;
> for (int i = 0; i<other.size_; i++) {
> update(other.records_[i]->key_, other.records_[i]->data_);
> }
> }
> template <class TYPE>
> SimpleTable<TYPE>::SimpleTable(SimpleTable<TYPE>&& other) {
> size_ = swap(other.size_);
> max_ = swap(other.max_);
> records_ = swap(other.records_);
> }
>
> template <class TYPE>
> bool SimpleTable<TYPE>::update(const string& key, const TYPE& value) {
> int idx = search(key);
> if (idx == -1) {
> if (size_ == max_) {
> grow();
> }
> records_[size_++] = new Record(key, value);
> for(int i=0;i<size_;i++) {
> if(records_[i]->key_ > records_[size_-1]->key_) {
> Record* tmp = records_[i];
> records_[i] = records_[size_-1];
> records_[i] = tmp;
> }
> }
> }
> else {
> records_[idx]->data_ = value;
> }
> return true;
> }
> template <class TYPE>
> bool SimpleTable<TYPE>::remove(const string& key) {
> int idx;
> idx=search(key);
> if(idx!=-1){
> delete records_[idx];
> for(int i=idx;i<size_-1;i++){
> records_[i]=records_[i+1];
> }
> size_--;
> return true;
> } else {
> return false;
> }
> }
> template <class TYPE>
> bool SimpleTable<TYPE>::find(const string& key, TYPE& value) {
> int idx = search(key);
> if (idx == -1) {
> return false;
> } else {
> value = records_[idx]->data_;
> return true;
> }
> }
>
> template <class TYPE>
> const SimpleTable<TYPE>& SimpleTable<TYPE>::operator=(const
> SimpleTable<TYPE>& other) {
> if (this != &other) {
> if(records_){
> delete[] records_;
> }
> records_ = new Record*[other.max_];
> max_ = other.max_;
> size_ = 0;
> for (int i = 0; i<other.size_; i++) {
> update(other.records_[i]->key_,
> other.records_[i]->data_);
> }
>
> }
> return *this;
> }
> template <class TYPE>
> const SimpleTable<TYPE>& SimpleTable<TYPE>::operator=(SimpleTable<TYPE>&&
> other) {
> swap(records_, other.records_);
> swap(size_, other.size_);
> swap(max_, other.max_);
> return *this;
> }
> template <class TYPE>
> SimpleTable<TYPE>::~SimpleTable() {
> if (records_) {
> int sz=size_;
> for(int i=0;i<sz;i++){
> remove(records_[0]->key_);
> }
> }
> }
>
> template <class TYPE>
> class HashTable :public Table<TYPE> {
> // This is the internal structure for array elements for hastable
> struct Record {
> TYPE data_; // data per array element
> string key_;//key to lookup for data element
> Record* next_; // next record to create linkly linked
> list for bucketing
> // Constructor to set values of Record
> Record(const string key, const TYPE data) {
> key_ = key;
> data_ = data;
> next_=nullptr;
> }
> //empty Constructor that sets values to empty safe
> state
> Record(){
> key_="";
> data_=0;
> next_=nullptr;
> }
> //Returns key of Record
> string getKey() const {
> return key_;
> }
> //Sets key of Record
> string setKey(string key) {
> key_=key;
> }
> //Returns data member of Record
> TYPE getData() const {
> return data_;
> }
> //Sets data member of Record
> void setData(TYPE data) {
> data_=data;
> }
> //Gets next element in linked list for bucketing
> Record *getNext() const {
> return next_;
> }
> //Sets next element in linked list for bucketing
> void setNext(Record *next) {
> next_ = next;
> }
>
> };
>
> Record** table_; //the table
> int size_;//size_
> int cap;//max number of records allowed in table
> std::hash<std::string> hash;//hash function used
>
> public:
> HashTable(int maxExpected);
> HashTable(const HashTable& other);
> HashTable(HashTable&& other);
> int numRecords();
> bool isEmpty();
> virtual bool update(const string& key, const TYPE& value);
> virtual bool remove(const string& key);
> virtual bool find(const string& key, TYPE& value);
> virtual const HashTable& operator=(const HashTable& other);
> virtual const HashTable& operator=(HashTable&& other);
> virtual ~HashTable();
> };
> /* none of the code in the function definitions below are correct. You can
> replace what you need
> */
> //returns size of table
> template <class TYPE>
> int HashTable<TYPE>::numRecords() {
> return size_;
> }
> //returns if hashtable has no records been inserted
> template <class TYPE>
> bool HashTable<TYPE>::isEmpty(){
> return size_==0;
> }
> //Constructor that allocates memory equal to passed amount in maxExpected and
> sets hashtable to empty state
> template <class TYPE>
> HashTable<TYPE>::HashTable(int maxExpected) : Table<TYPE>() {
> int size_=0;
> table_=new Record*[maxExpected]();
> cap=maxExpected;
> }
> //Copy Constructor that creates a copy of passed hashtable as argument to
> create a new copy of including memory allocations
> template <class TYPE>
> HashTable<TYPE>::HashTable(const HashTable<TYPE>& other) {
> table_ = new Record*[other.cap];
> size_=other.size_;
> hash = other.hash;
> cap=other.cap;
> for(int i=0;i<cap;i++){
> if(other.table_==nullptr){
> continue;
> }
> string key=other.table_[i]->getKey();
> table_[i]->key_=key;
> TYPE data=other.table_[i]->getData();
> table_[i]->setData(data);
> }
> }
> //Move constructor that moves the hashtable passed into the current table
> being constructed
> template <class TYPE>
> HashTable<TYPE>::HashTable(HashTable<TYPE>&& other) {
> swap(size_,other.size_);
> swap(cap,other.cap);
> swap(table_,other.records_);
> swap(hash,other.hash);
> }
> //Updates record with the string passed to the new data for the record's data
> element and returns true if found/updated otherwise false
> template <class TYPE>
> bool HashTable<TYPE>::update(const string& key, const TYPE& value) {
> int hashvalue=hash(key)%cap;
> Record* prev=nullptr;
> Record* entry=table_[hashvalue];
>
> while (entry != nullptr && entry->getKey() != key) {
> prev=entry;
> entry=entry->getNext();
> }
>
> if (entry == nullptr) {
> entry = new Record(key, value);
> if (prev == nullptr) {
> // insert as first bucket
> table_[hashvalue] = entry;
> } else {
> prev->setNext(entry);
> }
> } else {
> // just update the value
> entry->setData(value);
> }
> size_++;
> return true;
> }
> //Removes the record with the string passed for the key value and returns
> true if removed otherwise false if not found
> template <class TYPE>
> bool HashTable<TYPE>::remove(const string& key) {
> int hashValue = hash(key)%cap;
> Record *prev = nullptr;
> Record *entry = table_[hashValue];
>
> while (entry != nullptr && entry->getKey() != key) {
> prev = entry;
> entry = entry->getNext();
> }
>
> if (entry == nullptr) {
> // key not found
> return false;
> }
> else {
> if (prev == nullptr) {
> // remove first bucket of the list
> table_[hashValue] = entry->getNext();
> } else {
> prev->setNext(entry->getNext());
> }
> delete entry;
> }
> size_--;
> return true;
> }
> //Finds value in table and updates with the value passed if found returns
> true otherwise false
> template <class TYPE>
> bool HashTable<TYPE>::find(const string& key, TYPE& value) {
> int hashValue = hash(key)%cap;
> Record* entry =table_[hashValue];
> while (entry != nullptr) {
> if (entry->getKey() == key) {
> value=entry->getData();
> return true;
> }
> entry = entry->getNext();
> }
> return false;
> }
> //Copy Assignment Operator creates copy of hashtable passed into current
> hashtable
> template <class TYPE>
> const HashTable<TYPE>&HashTable<TYPE>::operator=(const HashTable<TYPE>&
> other) {
> if (table_) {
> delete[] table_;
> }
> table_ = new Record*[other.cap];
> size_=other.size_;
> hash = other.hash;
> cap=other.cap;
> for(int i=0;i<cap;i++){
> if(other.table_==nullptr){
> continue;
> }
> string key=other.table_[i]->getKey();
> table_[i]->key_=key;
> TYPE data=other.table_[i]->getData();
> table_[i]->setData(data);
> }
> return *this;
> ;
>
> }
> //Moves Assignment Operator which moves passed hashtable into current
> hashtable
> template <class TYPE>
> const HashTable<TYPE>& HashTable<TYPE>::operator=(HashTable<TYPE>&& other) {
> swap(size_,other.size_);
> swap(table_,other.table_);
> swap(hash,other.hash);
> swap(cap,other.cap);
> return *this;
>
> }
> //Destructor this destroys the hashtable when it goes out of scope or is
> called directly
> template <class TYPE>
> HashTable<TYPE>::~HashTable() {
> // destroy all buckets one by one
> for (int i = 0; i < cap; ++i) {
> Record *entry = table_[i];
> while (entry != nullptr) {
> Record *prev = entry;
> entry = entry->getNext();
> delete prev;
> }
> table_[i] = nullptr;
> }
> // destroy the hash table
> delete [] table_;
> }
> G++ Version/Toolchain used as with gcc -v:
> Using built-in specs.
> COLLECT_GCC=/usr/bin/g++
> COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/5/lto-wrapper
> Target: x86_64-linux-gnu
> Configured with: ../src/configure -v --with-pkgversion='Ubuntu
> 5.4.0-6ubuntu1~16.04.4' --with-bugurl=file:///usr/share/doc/gcc-5/README.Bugs
> --enable-languages=c,ada,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr
> --program-suffix=-5 --enable-shared --enable-linker-build-id
> --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix
> --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu
> --enable-libstdcxx-debug --enable-libstdcxx-time=yes
> --with-default-libstdcxx-abi=new --enable-gnu-unique-object
> --disable-vtable-verify --enable-libmpx --enable-plugin --with-system-zlib
> --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo
> --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-5-amd64/jre --enable-java-home
> --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-5-amd64
> --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-5-amd64
> --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar
> --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686
> --with-abi=m64 --with-multilib-list=m32,m64,mx32 --enable-multilib
> --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu
> --host=x86_64-linux-gnu --target=x86_64-linux-gnu
> Thread model: posix
> gcc version 5.4.0 20160609 (Ubuntu 5.4.0-6ubuntu1~16.04.4)
> Huge Thanks for any help,
> Nick