std with arry index (not iterator) gives segmentation fault - c++

I have defined a vector like this in the header file
class entry
{
public:
int key;
int next;
};
std::vector<entry *> TB;
in the cpp file, I wrote:
int s1, val;
s1 = 10; val = 2;
gh = (TB.size() % s1);
However when I want to write something to it, I get segmentation fault
TB[gh]->key = val;
What is the problem with the assignment?

The vector has no elements. Use push_back() or insert() to add elements to the vector:
entry* e = new entry();
e->key = val;
e->next = 0;
TB.push_back(e); // Append to vector.
TB.insert(TB.begin(), e); // Insert at beginning of the vector.
When destroying the vector TB you must iterate over the elements and delete each individually (or use a smart pointer as the element type, such as boost::shared_ptr<entry> or std::unique_ptr<entry>).
You could provide a constructor(s) for entry to make the addition of an entry to TB more concise:
class entry
{
public:
entry(int a_key, int a_next = 0) : key(a_key), next(a_next) {}
int key;
int next;
};
TB.push_back(new entry(val));
TB.insert(TB.begin(), new entry(val));

The TB vector is empty, until you fill it with some pointers.
E.g. TB.resize(100);.
The points in TB should point to valid addresses, i.e. some valid entry instances. E.g. TB[0] = new entry();.
So:
std::vector<entry *> TB(1);
TB[0] = new entry();
TB[0]->key = 42;

Related

array class member, with dynamically changeable length during runtime

I am trying to make a network application. Its class blueprint is roughly like this-
class Node
{
public:
// member functions
private:
int nodeID;
// other members
};
class NodeNetwork
{
public:
// member functions
private:
Node nodeArray[MAX_NODES];
// other members
};
Here, the Node class will deal with each node and the NodeNetwork is used to deal with the complete network.
The actual number of nodes in nodeArray can vary from 0 to MAX_NODES during runtime, i.e., it may not always be MAX_NODES, the number of nodes can be increased or decreased during runtime. Moreover, when the program starts the number will always be 0, after that it will start increasing.
I am using Node nodeArray[MAX_NODES];, but I think it's a serious wastage of space as not always I will have MAX_NODES nodes at runtime. So I am looking for ways to optimize it. I want it so that it starts with a zero-length array, but the size can be increased or decreased subjected to the above constraints based on the nodes added or removed at runtime. I researched on the internet but did not find any concrete answer.
I hope someone can help me solve this problem, thanks in advance.
You can use dynamically array allocation for this purpose:
int* arr = new int[5];
..and anytime you wish to change the number of elements:
int size = 5;
int* arr = new int[size] {};
int* new_arr = new int[size + 1];
for (int i = 0; i < size; i++)
{
new_arr[i] = arr[i];
}
delete[] arr;
arr = new_arr;
// Now arr has a storage capacity of 6 elements
..so for your case you can write:
Node* nodeArray = nullptr; // nullptr == null pointer
But this can take a lot of time for huge arrays.
So preferably, you can use std::vector:
#include <iostream>
#include <vector>
int main()
{
std::vector<int> vec{ 1, 2, 3, 4, 5 };
vec.push_back(6); //Insert a new element
std::cout << vec[0]; // Accessing an element is the same as an array
}
..so for your case:
// {} is just for initialization, not exactly mandatory
std::vector<Node> nodeArray{};
You can use std::vector instead of array. That is, you can make the data member nodeArray to be a std::vector<Node> as shown below.
#include <iostream>
#include<vector>
class Node
{
public:
//constructor for initializing nodeID data member
Node(int pnodeID): nodeID(pnodeID)
{
}
//getter for nodeId
int getId() const
{
return nodeID;
}
private:
//always initialize built in type in local/block scope so that they don't have indeterminate value
int nodeID = 0;
// other members
};
class NodeNetwork
{
public:
// member function to add Node
void addNode(const Node& n)
{
nodeArray.push_back(n);
}
//member function to print out the current nodes
void display() const
{
std::cout<<"Network has the following nodes: "<<std::endl;
for(const Node& elem: nodeArray)
{
std::cout<<elem.getId()<<std::endl;
}
}
private:
std::vector<Node> nodeArray; //used std::vector instead of array
// other members
};
int main()
{
//create Node objects
Node node1{1};
Node node2{2};
Node node3{3};
NodeNetwork network1;
//add node1 into the network1's nodeArray data member
network1.addNode(node1);
//add node2 into the network1's nodeArray data member
network1.addNode(node2);
//display all nodes into network1
network1.display();
return 0;
}
In the above demo we have added elements into the nodeArray data member by using std::vector::push_back member function.
The output of the above program can be seen here:
Network has the following nodes:
1
2

What is the most efficient way to add and initialize a new std::map element?

Say, if I have the following map, where each element contains an array:
struct STRUCT{
int value;
std::vector<MY_DATA> myArr;
};
std::map<UINT, STRUCT> myMap;
And then if I want to add a new element to that map and also initialize it at the same time:
//But, let's say we have a 'STRUCT' with a large number of items in the vector
std::vector<MY_DATA> arr;
arr.resize(0x10000); //Arbitrary
int val = 123;
addToMap(&arr, val);
From what I understand I have the following ways to do it:
void addToMap1(UINT id, std::vector<MY_DATA>* pArr, int val)
{
//Method 1
STRUCT myStruct;
myStruct.myArr = *pArr;
myStruct.value = val;
myMap[id] = myStruct;
}
void addToMap2(UINT id, std::vector<MY_DATA>* pArr, int val)
{
//Method 2
myMap[id] = STRUCT();
STRUCT* pS = &myMap[id];
pS->myArr = *pArr;
pS->value = val;
}
void addToMap3(UINT id, std::vector<MY_DATA>* pArr, int val)
{
//Method 3
myMap[id] = STRUCT();
std::map<UINT, STRUCT>::iterator itr = myMap.find(id);
STRUCT* pS = &itr->second;
pS->myArr = *pArr;
pS->value = val;
}
void addToMap4(UINT id, std::vector<MY_DATA>* pArr, int val)
{
//Method 4
std::pair<std::map<UINT, STRUCT>::iterator, bool> prNew =
myMap.insert(std::pair<UINT, STRUCT>(id, STRUCT()));
ASSERT(prNew.second); //It must have not existed before!
STRUCT* pS = &prNew.first->second;
pS->myArr = *pArr;
pS->value = val;
}
But what is the most efficient way to do it?
If your intent implies overwriting the existing data for the key that is already present in the map, then just plain
void addToMap(UINT id, const std::vector<MY_DATA>* pArr, int val)
{
STRUCT &pS = myMap[id];
pS.value = val;
pS.myArr = *pArr;
}
will do the trick quite efficiently. It is not clear why in your existing "methods" you insist on first saving a default-constructed STRUCT() into myMap[id]. This is completely unnecessary.
The other optimization opportunities would involve:
Moving data from the existing vector instead of copying it (if possible)
Not even constructing the source vector, and constructing the target vector directly in the map (if possible)
It the source vector is required to exist as an independent object (and is long-lived), then a pointer to that vector can be stored in the map instead of a full copy
But it is not clear from your description whether this is applicable in your case.
Note that you cannot use emplace for this purpose since emplace does not do what you want to do in this case: it does not overwrite data for existing keys. What we'd need in this case is a forwarding version of insert_or_assign, but alas it does not exist.
You might move ressource, something like:
void addToMap(UINT id, std::vector<MY_DATA>&& arr, int val)
{
auto& s = myMap[id];
s.myArr = std::move(arr);
s.value = val;
}

R-value overloaded Operator string assignment error

I am having some trouble figuring out why i get Unhandled exception at 0x003DBD00 in Project10.exe: 0xC0000005: Access violation reading location 0xCDCDCDE5. It seems to pop up at a string assignment operator similar to this: std::string x = std::move(std::string y); Please see code below for more information.
The call starts from here: *members += NVPair<std::string, std::string>(n,v);
FYI members is members = new List <NVPair <std::string, std::string>, DATA_MEMBERS_PER_OBJECT>(); where DATA_MEMBERS_PER_OBJECT is 4
List class declarations:
auto list = new List <T, OBJECTS_PER_JSON_FILE>(); //Not used in this process
auto members = new List <NVPair <std::string, std::string>, DATA_MEMBERS_PER_OBJECT>();
Operator call:
n = trim(trim(getName(line)),'"'); //Trim removes extra characters from line and returns Name
v = trim(trim(getValue(line)),'"'); //or Value as a std::string
*members += NVPair<std::string, std::string>(n,v);
List Class
//List.h
#include <iostream>
#include <string>
template <typename T, unsigned int n>
class List{
T *Array[n];
size_t elements;
T dummy;
public:
List(){ elements = 0u; }
size_t size() const { return elements; }
const T& operator[](unsigned int i) const{...}
void operator+=(const T& add){ //adds a copy to the element
*Array[elements] = add;
elements++;
}
void operator+=(T&& add){ //moves element
*Array[elements] = std::move(add);
elements++;
}
Name Value pair Class
//NVPair.h
#include <iostream>
#include <string>
template <typename T, typename B>
class NVPair{
T Name;
B Value;
public:
NVPair(){ Name = ""; Value = ""; }
NVPair(T n, B v){ Name = n; Value = v; }
T name() const { return Name; }
B value() const{ return Value; }
NVPair& operator=(const NVPair& add){
Name = add.Name;
Value = add.Value;
return *this; }
NVPair& operator=( NVPair&& add){
Name = std::move(add.Name);
Value = std::move(add.Value);
return *this; }
};
I have been trying to debug it and it fails and goes into xstring at Name = std::move(add.Name) inside the NVPair =function.
Any help is much appreciated!
Edit: Looks like I was being very vague (Sorry first time). So The main program reads information from a file that contains Name and value pairs. It then creates a List object that is an array of pointers to Name value pair objects. So T * Array[n] is an array of T pointers. The purpose is to store information from a file that looks like this:
{
"Name" : "Cat"
"type" : "animal"
}
and so on...
The array member inside your List class is never initialized, but you are referencing it in the += operator. Also, I presume you want an array of NVPairs not array of NVPair pointers
Try doing something along the lines of:
template <typename T>
class List
{
T Array[n];
size_t size;
size_t elements;
T dummy;
public:
List(size_t maxSize) : size(maxSize), elements(0)
{
Array = new T[size];
}
void operator+=(T&& add)
{ //moves element
//This was where it was failing because Array was not defined
Array[elements] = std::move(add);
elements++;
}
//The rest of the class
}
The constructor will create an array of NVPairs, then you assign the values as normal. Notice that you need 2 variables, one for the size, one for the number of elements currently in the array.

c++ Heap warning: Free heap block modified after it was freed

I have the following class and code:
template <class T>
class HashTable {
struct Pair{
T element;
int key;
Pair(T element, int Key) : element(element), key(key) {};
};
int table_size;
int counter;
List<Pair> (*elements);
void changeTableSize(int newSize){
List<Pair> *temp = new List<Pair>[newSize];
for (int i = 0; i < table_size; i++){
for (typename List<Pair>::Iterator j = elements[i].begin(); j != elements[i].end(); j++){
Pair p = *j;
temp[p.key % newSize].insert(Pair(p.element, p.key));
}
}
delete[] elements;
elements = temp;
table_size = newSize;
}
public:
HashTable() : table_size(100), counter(0){
elements = new List<Pair>[table_size];
};
void insert(T data, int key){
if (member(key)){
throw ElementAlreadyExists();
}
elements[key % table_size].insert(Pair (data, key));
counter++;
if (counter == table_size){
changeTableSize(table_size*2);
}
};
When I call changeTableSize() the first time, everything is fine. When I call it the second time my program crashes saying "warning: HEAP: Free Heap block 006618C0 modified at 006618D4 after it was freed" right after the allocation for temp. What can cause this?
If originalSize > table_size then you are performing an illegal memory access in the inner 'for' loop.
Remove the 'originalSize' argument that you are passing to the function.
Use the class variable 'table_size' instead, and update it to the new size before you return.
Also, make sure that class Pair has a copy-constructor properly defined and implemented:
Pair(const Pair& pair)
{
// For each variable x of pair, that points to dynamically-allocated memory:
// this->x = new ...
// memcpy(this->x,pair.x,...)
// For each variable y of pair, that doesn't point to dynamically-allocated memory:
// this->y = pair.y
}
Otherwise, you might have two different instances of class Pair with internal variables pointing to the same dynamically-allocated memory. And when one instance is destroyed, the internal variables of the other instance will point to an already-freed memory.

Adding something to an array

I have a class, whereby one of its elements is of another class, but is an array
class B
{
public:
B() //default
{
element = new A [1]; count = 0;
}
A add(A place)
{
A* newArr;
newArr = new A [count+1];
newArr = element;
newArr[count+1] = place;
delete element;
return newArr[count+1];
}
protected:
int count;
A* element;
};
I am trying to use dynamic arrays, where I when adding the element, I make a new array dynamically, initilzed to the size of the old array plus 1, then copy the elements of the old array to the new array, and then delete the old array. But I am unsure of how to modify the array that's already within the class, if that makes sense (Basically what to return in my add method).
In C++ there's no notion of resizing arrays once declared. Same goes for dynamic arrays, which can't be resized once allocated. You can, however, create a bigger sized array, copy all elements from the older array to the newer one and delete the old one. This is discouraged and would not be performant.
Using std::vector would allow you to add at will and will also keep track of its size, so you don't need count as part of the class.
class B
{
// no need to allocate, do add when required i.e. in B::add
B() : count(), elements() { }
A add(A place)
{
// unnecessarily allocate space again
A *new_elements = new A[count + 1];
// do the expensive copy of all the elements
std::copy(elements + 0, elements + count, new_elements);
// put the new, last element in
new_elements[count + 1] = place;
// delete the old array and put the new one in the member pointer
delete [] elements;
elements = new_elements;
// bunp the counter
++count;
return place; //redundant; since it was already passed in by the caller, there's no use in return the same back
}
protected:
size_t count;
A *elements;
};
The above code perhaps does what you want but is highly discouraged. Use a vector; you code will simply become
class B
{
// no need of a constructor since the default one given by the compiler will do, as vectors will get initialized properly by default
void Add(A place)
{
elements.push_back(place);
// if you need the count
const size_t count = elements.size();
// do stuff with count here
}
protected:
std::vector<A> elements;
};
A more thorough example would be to more closely mimic std::vector:
template<typename T>
class B
{
private: // don't put data under a protected access!
std::size_t _capacity;
std::size_t _size;
T* _elements;
public:
B() : _capacity(0), _size(0), _elements(nullptr) {}
// other methods
void add(const T& t)
{
if (_size >= _capacity) // need to resize the array
{
_capacity++; // you can make this better by increasing by several at a time
T* temp = new T[_capacity];
std::copy(_elements, _elements + _size, temp);
delete [] _elements;
_elements = temp;
}
_elements[_size++] = t;
}
};