push_front segmentation fault 11 c++ - c++

I have tried looking around and tried all the solutions but I cannot seem to fix my problem. I know i get the segmentation fault on the push_front line but I am just lost. Here is the code-
#include <iostream>
#include <fstream>
#include <sstream>
#include <list>
using namespace std;
typedef std::list<int> hSlots; //the list
typedef hSlots* hTable; //an array of lists
class HashTable
{
private:
int p; //p=number of slots in the hash table
hTable tmpPtr;
hTable *table;
public:
HashTable(int p1);
int h1(int k);
~HashTable();
void chainedHashInsert(int x);
};
HashTable::HashTable(int p1)
{
p=p1;
hTable tTable[p];
//initializing to empty lists
for (int i=0; i<p; i++)
{
tmpPtr = new hSlots;
tTable[i] = tmpPtr;
}
table = tTable;
}
//destrcutor
HashTable::~HashTable()
{
delete table;
delete tmpPtr;
}
void HashTable::chainedHashInsert(int x)
{
tmpPtr = table[h1(x)];
cout<<"hashed"<<endl;
tmpPtr->push_front(x); //segmentation fault
}
int HashTable::h1(int k)
{
int z = k%p;
return z;
}
I have not used a lot of lists so I'm not too sure

Maybe this could be a proper answer after all.
Your problems arise from doing memory management (wrong) manually, when really there is no need to, in C++.
Here's my take on it using direct automatic memory management in C++:
#include <vector>
#include <list>
using namespace std;
template <typename T, typename hSlots = std::list<T> >
class HashTable
{
private:
int p; //p=number of slots in the hash table
std::vector<hSlots> table;
int getbucket(int k) { return k%p; }
public:
HashTable(int p1) : p(p1), table(p1) {}
void chainedHashInsert(int x)
{
auto& tmpPtr = table[getbucket(x)];
tmpPtr.push_front(x);
}
};
int main()
{
HashTable<int> table(37);
}

since tTable is local variable to HashTable, it disappears when HashTable method returns and leaves table as a dangling pointer.
So to get rid of that do as below; create a space for table using new.
HashTable::HashTable(int p1)
{
p=p1;
table = new ttTable[p];
//initializing to empty lists
for (int i=0; i<p; i++)
{
tmpPtr = new hSlots;
table[i] = tmpPtr;
}
}

table = tTable;
This line is the problem (or at least one of them).
You're stashing a pointer to an automatic object into a member variable, then dereferencing (and deleting!) it later, once the object has been destroyed.

Related

I want to know how to pass an array of pointer objects into my constructor in C++

In my header file for my PCBTable.cpp I have this:
class PCBTable {
private:
PCB* table[];
}
In my PCBTable.cpp I am trying to create a constructor that initializes the table to a blank table of PCB objects, with the size of my parameter and it looks like this
PCBTable::PCBTable(int size) {
table = new PCB*[size];
}
However I get the error that table must be a modifiable value(E0137), and that array type PCB*[] is not assignable.
I've tried messing around with this but I can't get it to work.
new T[...] returns a T* pointer, where T in your case is PCB*, thus you are asking new[] to return a PCB** pointer, which cannot be assigned to a PCB*[] 1 fixed array, hence the error.
(1 you are not specifying the size of the array, which is invalid syntax)
You need to change your table declaration to match what new[] actually returns, eg:
class PCBTable {
private:
PCB** table;
int table_size;
public:
PCBTable(int size);
~PCBTable();
};
PCBTable::PCBTable(int size) : table_size(size) {
table = new PCB*[size];
for (int i = 0; i < size; ++i) {
table[i] = new PCB;
}
}
PCBTable::~PCBTable() {
for (int i = 0; i < table_size; ++i) {
delete table[i];
}
delete[] table;
}
Alternatively, if you just need an array of objects, rather than an array of pointers to objects:
class PCBTable {
private:
PCB* table;
int table_size;
public:
PCBTable(int size);
~PCBTable();
};
PCBTable::PCBTable(int size) {
table_size = size;
table = new PCB[size];
}
PCBTable::~PCBTable() {
delete[] table;
}
That being said, you really should be using std::vector instead of new[]/delete[] manually. And if you are using C++11 or later, use std::unique_ptr or std::shared_ptr instead of raw pointers, eg:
#include <vector>
#include <memory>
class PCBTable {
private:
std::vector<std::unique_ptr<PCB>> table;
public:
PCBTable(int size);
};
PCBTable::PCBTable(int size) : table(size) {
for (auto &elem : table) {
elem = std::make_unique<PCB>();
}
}
Or:
#include <vector>
#include <memory>
class PCBTable {
private:
std::vector<PCB> table;
public:
PCBTable(int size);
};
PCBTable::PCBTable(int size) : table(size) {
}
There seems to be some confusion here. Arrays (declared like int foo[12]) are fixed-size at compile time and can be found on the stack. If you want a dynamically sized array, a list whose size is defined at runtime and isn't necessarily known at compile time, that needs to be a pointer. If the elements you want in your array are themselves pointers, it will have to be a pointer to pointers.
class PCBTable {
private:
PCB** table;
}
PCBTable::PCBTable(int size){
table = new PCB*[size];
}
Or, better yet, you could use std::vector, which gives you all the best of both worlds.
#include <vector>
class PCBTable {
private:
std::vector<PCB*> table;
}
PCBTable::PCBTable(int size){
table.resize(size);
}
You can use std::vector any way you would use a normal array. This also provides the dual benefit of not having to store the array size in an external variable, as table.size() takes care of that for you.

Accessing a structure through another structure member in C++

I'm trying to access a structure using another structure. From the below program, element is the member of Node. At this line " temp->element *e_temp;", I couldn't link the "element" member of Node to the "elements" structure object.
compile error says "'e_temp' was not declared in this scope". What am I missing?
#include <vector>
#include <cstdlib>
using namespace std;
typedef struct Elements
{
int data;
struct Elements *next;
}elements;
typedef struct Node
{
int sno;
elements *element;
struct Node *next;
}node;
void add(int sno, vector<int> a)
{
node *temp;
temp = new node;
temp->element *e_temp;
e_temp = new elements;
temp->sno = sno;
while(a.size())
{
temp->e_temp->data = a[0];
temp->e_temp = temp->e_temp->next;
a.erase(a.begin());
}
}
int main()
{
vector<int> a{1,2,3};
int sno = 1;
add(sno, a);
return 0;
}
If you're just looking to declare a local you can do auto e_temp = new elements but what i think you want is this for that line temp->element = new elements;
and then follow up with the rest of your code to reference temp's element instead of e_temp.
temp->element->data = a[0];
temp->element = temp->element->next
Also, i'd try to get out the habit of using new and use std::shared_ptr and std::unique_ptr instead.
The correct declaration for e_temp is
elements * e_temp;
but e_temp is not use of any part of your code.

How to swap array using pointer when array is a data member of a class

I am trying to swap the content in the arrays by swapping the pointers pointing to the two arrays.
My method is the same as what Daniel answered in this question: Swap arrays by using pointers in C++. But the difference is that my array will be a member in a class.
My code can be compiled successfully, but the output results are quite weird.
This is my header file:
#include <stdio.h>
#include <iostream>
class Map
{
public:
Map(int times); // Create an empty map (i.e., one with no key/value pairs)
int size(); // Return the number of key/value pairs in the map.
void dump();
void swap(Map &other);
int *retrieve();
void setptr(int *newptr);
private:
int *ptr;
int array_1[5];
};
Here is my implementation:
#include "Map.h"
#include <iostream>
using namespace std;
Map::Map(int times) {
for (int i = 0; i < 5; i++) {
array_1[i]=i*times;
}
ptr=array_1;
}
void Map::dump() {
ptr=array_1;
for (int i = 0; i < 5; i++) {
cout << *ptr << endl;
ptr++;
}
for (int i = 0; i < 5; i++) {
ptr--;
}
}
void Map::swap(Map &other) {
int *temp;
temp = this->ptr;
this->ptr = other.retrieve();
other.setptr(temp);
}
int *Map::retrieve() {
return ptr;
}
void Map::setptr(int *newptr) {
ptr=newptr;
}
Can anyone tell me what is wrong and how to implement it smartly?
The following code runs fine:
#include <stdio.h>
#include <iostream>
#include <conio.h>
using namespace std;
class Map
{
public:
Map(int times); // Create an empty map (i.e., one with no key/value pairs)
int size(); // Return the number of key/value pairs in the map.
void dump();
void swap(int &other);
int *retrieve();
void setptr(int *newptr);
private:
int *ptr;
int array_1[5];
};
Map::Map(int times){
for (int i=0;i<5;i++){
array_1[i]=i*times;
}
ptr=array_1;
}
void Map::dump(){
for (int i=0;i<5;i++)
{
cout<<ptr[i]<<endl;
}
}
void Map::swap(int &other){
int *temp;
temp=this->ptr;
this->ptr=&other;
other = *temp;
}
int *Map::retrieve(){
return ptr;
}
void Map::setptr(int *newptr){
ptr=newptr;
}
int main()
{
Map m(2);
Map n(3);
m.dump();
m.swap(*n.retrieve());
m.dump();
getchar();
}
1) Added a main function
2) Changed Swap function
But the problem that christopher pointed out will still persist i.e the pointer will point to an array in another object.
Edit: You probably need something like this:
void Map::swap(Map &other){
Map *temp;
temp=this;
*this = other;
other = *temp;
}
Map *Map::retrieve(){
return this;
}
Note: it is probably not elegant.
The problem with your design is that the pointer refers to an array in the same object.
Suppose you have to objects a and b. If you swap their pointers, a.ptr will point to b.array_1 which contains the data. reciprocally b.ptr will point to a.array1.
Unfortunately if one of the object -- say b -- gets destroyed (because it was a local object that goes out of scope, or for whatever reason) the pointer of the remaining object would point to an array which doesn't exist anymore. This is UB.
To solve your issue, you'd neet to allocate an array dynamically in the constructor. Get rid of array_1 completely:
Map::Map(int times){
ptr=new int[5]; // or better define a constant to avoid hard coded sizes
for (int i=0;i<5;i++){
ptr[i]=i*times;
}
}
Note that if you use pointers, you need to ensure the invarients on it. This means that you should define also the copy constructor and the assignment operator (to avoid the ptr to be blindly copied), as well as a destructor (to delete the dynamically allocated array).
P.S.: I suppose that you are learning C++ and are not yet familiar with vectors. These would avoid all the hassles here
Edit: if you experience your problem before any object is destroyed, it's because of a bad implementation of dump(): you increment the pointer there in, so that it will no longer point to the start of the array.
void Map::dump(){
for (int i=0;i<5;i++){
cout<<ptr[i]<<endl; // don't change ptr value !!
}
}
One simple trick to avoid such problems, is to systematically declare the member functions that are not supposed to change the state of the object as const:
class Map {
...
void dump() const;
...
}
Then the compiler issues an error if you try to accidentally change a member.

Missing nullptr for undeclared array element

I am trying to make a basic HashMap. I am checking to see if an element exists at an index before inserting it there. When I insert my first element, it says that an element already exists at that position. I have gone through the debugger, and all of my values are as expected, except for map[hash]. I am anticipating a nullptr, but it is not coming. map[hash] has the following value:
- map[hash] 0xcdcdcdcd {key=??? value={...} next_element=??? } HashElement *
Can someone please explain to me what I am misunderstanding here? The unexpected result is on line 21 of HashMap.cpp. Here is the relevant code:
HashMap.h
#pragma once
#include <string>
#include "HashElement.h"
class HashMap
{
private:
HashElement **map;
int size;
public:
HashMap(int);
~HashMap();
int GetHash(int);
void Put(int, std::string);
};
HashMap.cpp
#include "HashMap.h"
#include <string>
HashMap::HashMap(int _size)
{
size = _size;
map = new HashElement*[size];
}
HashMap::~HashMap()
{
}
int HashMap::GetHash(int _key){
return _key % size;
}
void HashMap::Put(int _key, std::string _value){
int hash = GetHash(_key);
if (!map[hash]){ //Anticipated to be nullptr on first Put, but it skips to else
map[hash] = new HashElement(_key, _value);
}
else{
HashElement *lastElement = map[hash];
while (lastElement->next_element){
lastElement = lastElement->next_element;
}
lastElement->next_element = new HashElement(_key, _value);
}
}
HashElement.h
#pragma once
#include <string>
class HashElement
{
private:
int key;
std::string value;
public:
HashElement(int, std::string);
~HashElement();
HashElement *next_element;
int get_key();
std::string get_value();
};
HashElement.cpp
#include "HashElement.h"
HashElement::HashElement(int _key, std::string _value)
{
key = _key;
value = _value;
}
HashElement::~HashElement()
{
}
int HashElement::get_key(){
return key;
}
std::string HashElement::get_value(){
return value;
}
map[hash] is not a nullptr because you haven't initialized it to such.
map = new HashElement*[size];
Each element in the map array will have a random value after that line.
To fix this and initialize all elements to be nullptr:
map = new HashElement*[size]();
^^
map = new HashElement*[size];
Here, you are instantiating an array of size pointers, on the heap. As I understand your question, you are assuming that all of the instantiated pointers, in this new array, will be nullptr.
That is not the case. For "plain old data", or POD, its contents are not initialized by default. You'll have to explicitly initialize them:
for (size_t i=0; i<size; ++i)
map[i]=0;
... in the constructor

Error: std::bad_alloc at memory location 0x0038fd50

I have written a code using global heap. I need to redo the same operation a number of time. Every time I need to clear the heap and re-assign the data. but the vector::clear() function does not free the memory. so after some time the memory gets filled and the program terminates.
#include "stdafx.h"
#include <cstdio>
#include <vector>
using namespace std;
#define N 30000
typedef unsigned int uint;
class Node;
class Edge;
vector<Node*> nodes;
vector<Edge*> edges;
class Node
{
public:
Node(uint id): id(id)
{
nodes.push_back(this);
}
public:
uint id;
};
class Edge
{
public:
Edge(int nod1, int nod2)
: nodH(nod1), nodT(nod2)
{
edges.push_back(this);
}
bool Connects(Node* nod1, Node* nod2)
{
return (
(nod1->id == this->nodH && nod2->id == this->nodT) ||
(nod1->id == this->nodT && nod2->id == this->nodH));
}
public:
int nodH;
int nodT;
};
int _tmain(int argc, _TCHAR* argv[])
{
Node *nd;
for(long int i=0;i<N;i++)
{
for (int j=0;j<N;j++)
{
nd = new Node(j);
}
for (uint j=0;j<N;j++)
{
Edge* e = new Edge(j,N-j);
}
printf("%d %d ",nodes.size(),edges.size());
// Do something here like calling function etc.
nodes.erase(nodes.begin()+N/2);
nodes.clear();
edges.clear();
//nodes.~vector();
//edges.~vector();
printf("%d %d\n",nodes.size(),edges.size());
}
getchar();
return 0;
}
what can I do? I tried the vector::~vector() function. But that did not work.
Can anyone help me about how to free the "cleared" memory space?
Well known trick is to swap your vector with temporary created one
template< class T >
void clearVector( std::vector< T > & v )
{
std::vector< T > dummy;
std::swap( v, dummy );
}
BTW, using vector with raw pointers isn't a good idea. I'll suggest std::shared_ptr or similar. If (in some amazing reasons) you can't use smart pointers, then you should call function like this
struct die {
template <class T> void operator()( const T * p ) const { delete p; }
};
template< class InputIterator >
inline void kill_em_all( const InputIterator & begin, const InputIterator & end )
{
std::for_each( begin, end, die() );
}
...
kill_em_all( vector_to_clear.begin(), vector_to_clear.end() );
The reason vector.clear() does not delete the objects is that you keep raw pointers in the two vectors:
vector<Node*> nodes;
vector<Edge*> edges;
You either have to deallocate the elements yourself or, better, use smart pointers (for example, std::unique_ptr).
You are assigning one giant heap of memory for your application. Try to reduce your N to 100 for the start. bad_alloc usually means, that the runtime was not able to reserve memory.