This is the mail archive of the gcc-help@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: dynamically-allocated memory is uninitialized



On 2016-11-14 08:51 AM, Mason wrote:
> On 12/11/2016 08:04, nick wrote:
> 
>> On 2016-11-12 01:37 AM, Andrew Pinski wrote:
>>
>>> Anyways I think the problem is you assume
>>> new Record*[N]; will NULL out the array.  It does not.
>>
>> Shouldn't new overwrite that memory with a null block
>> or is new so stupid that it doesn't do this [...]
> 
> Hello,
> 
> First, while compiler bugs (or bugs in low-level supporting libraries)
> do exist, they are rare. Bugs lurk in user code 99.44% of the time.
> (I'm told that's a real statistic.)
> 
> Second, you expect dynamically-allocated memory to be zeroed. Consider the
> case where an app requests a large memory block, and intends to initialize
> it to non-0 values. Zeroing such a block would be a pure waste of CPU.
> 
> cf. also short-comings of strncpy()
> 
> Regards.
> 
It was my fault actually anyhow I do have one more question with my code which I will paste below which has 
been causing me issues. 
I for some reason have not figured out how to copy over the buckets for the table,
if you have any ideas please let me known and this is what is causing issues:
while(entry!=nullptr && entry->next_){
		insert=new Record(entry->key_,entry->data_);
		std::cout<<table_[i]->next_->key_<<table_[i]->data_;
		entry=entry->getNext();
		insert=insert->getNext();
		}
#include <stdio.h>
#include <string>
#include <utility>
#include<iostream>
using namespace std;
/*The functions I updated for Simple Table are
1.search
2.grow
3.update
4.Bothe 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;
			}
			//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<other.cap;i++){
		if(other.table_[i]==nullptr){
			table_[i]=nullptr;
			continue;
		}
		string key=other.table_[i]->getKey();
		TYPE data=other.table_[i]->getData();
		table_[i]=new Record(key,data);
		Record* entry=other.table_[i]->getNext();		
		Record* insert=table_[i]->getNext();;
		while(entry!=nullptr && entry->next_){
		insert=new Record(entry->key_,entry->data_);
		std::cout<<table_[i]->next_->key_<<table_[i]->data_;
		entry=entry->getNext();
		insert=insert->getNext();
		}
	}
}
//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_[i]==nullptr){
		table_[i]=nullptr;
		continue;
	}
	string key=other.table_[i]->getKey();
        TYPE data=other.table_[i]->getData();
        table_[i]=new Record(key,data);
	Record* entry=other.table_[i]->getNext();		
	while(other.table_[i]->getNext()){
		table_[i]->next_=new Record(entry->key_,entry->data_);
		entry=entry->getNext();
		}
	}
	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_;
}


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]