I'm getting Segmentation Fault error. I'm fairly new to C++ so not really familiar with pointers and other such things. This seems to be a fundamental aspect but i can't seem to figure it out, I've spent countless hours on it.
I have 5 files element.h, element.cpp, heap.h, heap.cpp, main.cpp
error occurs on the line
h.setElements(e,i);
Which is a function in Heap.cpp
I know it has something to do with arrays
MAIN.CPP
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include "heap.h"
#include "element.h"
using namespace std;
int main(){
Heap h;
h = h.initialize(3);
for(int i=0;i<h.getCapacity(); ++i){
Element e;
e.setKey(i);
h.setElements(e,i); // Error occurs here
}
h.printHeap(h);
return 0;
}
HEAP.H
#ifndef heap_h
#define heap_h
#include "element.h"
#include <iostream>
using namespace std;
class Heap {
public:
Element* getElements();
void setElements(Element e,int index);
Heap initialize(int n);
void printHeap(Heap heap);
private:
int capacity;
int size;
Element* H;
};
#endif
HEAP.CPP
#include "heap.h"
Heap Heap::initialize(int n){
H = new Element[n];
Heap h;
h.capacity = n;
h.size = 0;
return h;
}
void Heap::printHeap(Heap heap){
for(int i=0;i<heap.capacity;++i){
cout << "Element " << i << " = " << H[i].getKey() << endl;
}
}
void Heap::setCapacity(int nCapacity ) {
capacity = nCapacity;
}
int Heap::getCapacity(void) {
return capacity;
}
void Heap::setSize(int nSize ) {
size = nSize;
}
int Heap::getSize(void) {
return size;
}
Element* Heap::getElements(void){
return H;
}
void Heap::setElements(Element e,int index){
H[index] = e;
}
You are getting the error because H is null.
The mistake is in the Heap::initialize(Element, int) method.
You are assigning the local variable H of the Heap object you are calling the method in, instead of the object you are returning.
Heap Heap::initialize(int n){
H = new Element[n]; // You are assigning H for the current heap object
Heap h; // Here you are creating a new Heap object
h.capacity = n;
h.size = 0;
return h; // You haven't assigned h.H
}
Why are you creating a new Heap object and returning it?
You can make the initialize method a void, like this:
void Heap::initialize(int n) {
H = new Element[n];
capacity = n;
size = 0;
}
Or if you need to return a new Heap object you can do it like this:
Heap Heap::initialize(int n) {
Heap h;
h.H = new Element[n];
h.capacity = n;
h.size = 0;
return h; // You have assigned h.H
}
Hope this was helpful.
Related
I'm working on an assignment to create a class called StringBuilder that is used for fast string concatenation. I'm supposed to store strings in a dynamic array and have methods such as Append(string) which adds a new string to the dynamic array. The method I'm currently struggling with is GetString() that creates a single string on the heap that is the length of all the strings in the dynamic array that have been added thus far.
the code I have so far is:
okay my main problem is my GetString() function prints out hello over and over again until I force quit the program in Xcode. I don't understand what inside that method is making that happen.
My header file:
#pragma once
#include <string>
using namespace std;
class StringBuilder
{
public:
StringBuilder();
//~StringBuilder();
void GetString();
void AppendAll(string*, int);
void Length();
void Clear();
void Append(string userString);
void DoubleArray(string*& allWords, int newCapacity);
private:
string* p_array;
int capacity = 5;
};
my .cpp file :
#include "StringBuilder.hpp"
#include <iostream>
#include <string>
using namespace std;
----------
void StringBuilder::Append(string userString)
{
int nextWordPosition = 0;
for(int i=0; i < capacity ; i++)
{
p_array[i] = userString;
cout << p_array[i] << endl;
nextWordPosition +=1;
if(capacity == nextWordPosition)
{
capacity *=2;
DoubleArray(p_array, capacity * 2);
}
}
nextWordPosition++;
}
void StringBuilder::DoubleArray(string*& allWords, int newCapacity)
{
string* p_temp = new string[newCapacity];
for(int i =0; i < newCapacity / 2; i++)
{
p_temp[i] = allWords[i];
}
delete[] allWords;
allWords = p_temp;
}
void StringBuilder:: GetString()
{
for(int i=0; i < capacity ; i++)
{
cout << p_array[i]<< endl;
}
}
my main.cpp file :
#include <iostream>
#include <string>
#include "StringBuilder.hpp"
using namespace std;
int main()
{
string testString = "hello";
string test = "world!";
StringBuilder Builder1;
Builder1.Append(testString);
Builder1.Append(test);
Builder1.GetString();
return 0;
}
I'm attempting to implement an intvector in C++ and am getting a "Segmentation fault: 11" error. I understand this has something to do with memory management, and considering how new I am to C++ it could definitely be a pretty minor mistake. I debugged the code with valgrind and was given messages such as the following:
Use of uninitialized value of size 8, Invalid read of size 4,Conditional jump or move depends on uninitialized value(s).
My best guess is it has something to do with how I'm implementing the arrays. I originally had the arrays stored on the heap but changed it to the stack and still got the same error. I've already implemented an intvector in java, so I was attempting to use similar logic here, which perhaps is part of the issue.
#include <iostream>
#include "IntVector.h"
#include <cmath>
using namespace std;
int num_elements = 0;
int array_size = 0;
int expansion_factor;
void IntVector::expandArray(){
int tempArr[array_size*2];
for(int i =0;i<array_size;i++){
tempArr[i] = array[i];
}
array = tempArr;
array_size = array_size * 2;
}
void IntVector::add(int val){
int tempArr[array_size];
if(array_size == num_elements){
expandArray();
array[num_elements] = val;
}
else{
for(int i = 0;i<array_size;i++){
tempArr[i] = array[i];
}
tempArr[num_elements] = val;
array = tempArr;
}
num_elements++;
}
void IntVector::remove(int index){
}
int IntVector::get(int index) const{
return index;
}
void IntVector::removeLast(){
}
void IntVector::set(int index, int val){
}
std::string IntVector::toString()const {
return "";
}
IntVector::IntVector(int initial_size){
int* array = new int[initial_size];
}
IntVector:: ~IntVector(){
delete[] array;
}
int main(){
IntVector v(0);
v.add(5);
}
#ifndef INTVECTOR_H_
#define INTVECTOR_H_
using std::cout;
class IntVector {
private:
int* array;
int num_elements;
int array_size;
int expansion_factor;
void expandArray();
public:
void add(int val);
void remove(int index);
int get(int index) const;
void removeLast();
void set(int index, int val);
std::string toString() const;
IntVector(int initial_size);
~IntVector();
};
#endif
As mention in the comments, there are definitely some holes in your understanding of C++. Really when dealing with header files you should have a main.cpp, someotherfile.h, someotherfile.cpp. That just best practices to avoid redefinition errors.
There was quite a bit wrong with the way you accessed the private variable. If a class has a private( or even public) variable you don't have to redeclare it each time you want to change its value.
There were one or two major flaws with the way you expanded the vector. If the vector size is initialized to 0 then 0*2 is still 0 so you never actually increased the size. Secondly, when you set the original array = to the new array the new array was just a local array. This means that the memory wasn't actually allocated permanently, once the function ended the temparr was destroyed.
I know this was probably a lot but if you have any question feel free to ask.
main.cpp
#include "IntVector.h"
int main()
{
IntVector v;
IntVector x(10);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.push(5);
v.print();
cout << endl;
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.push(5);
x.print();
return 0;
}
IntVector.h
#include <string>
#include <iostream>
using namespace std;
class IntVector {
private:
int *array;
int num_elements;
int array_size;
//int expansion_factor =; you would only need this if you plan on more than double the vector size
void expandArray(); //normally c++ array double in size each time they expand
public:
//Constructors
IntVector(); //this is a contructor for if nothing is called
IntVector(int initial_size);
//setters
void push(int val); //add
void pop(); //removelast
void remove(int index); //remove
void at(int index, int val); //set
//Getters
int at(int index);
//std::string toString(); I'm changing this to print
void print(); //will print the contents to the terminal
//Deconstructor
~IntVector();
};
IntVector.cpp
#include "IntVector.h"
//constructors
IntVector::IntVector() //no arguments given
{
array = new int[0];
num_elements = 0;
array_size = 0;
}
IntVector::IntVector(int initial_size)
{
array = new int[initial_size];
num_elements = 0;
array_size = initial_size;
}
void IntVector::expandArray()
{
int *tempArr;
if(array_size == 0){
array_size = 1;
tempArr = new int[1];
} else {
//make sure to allocate new memory
//you were creating a local array which was destroy after the function was completed
//using new will allow the array to exist outside the function
tempArr = new int[array_size * 2];
}
for (int i = 0; i < array_size; i++)
{
tempArr[i] = array[i];
}
//make sure to delete the old array otherwise there is a memory leak.
//c++ doesn't have a garbage collector
delete[] array;
array = tempArr;
array_size = array_size * 2;
}
void IntVector::push(int val)
{
num_elements++;
//checking if vector needs to increase
if (array_size <= num_elements)
{
expandArray();
array[num_elements-1] = val;
}
else
{
array[num_elements-1] = val;
}
}
void IntVector::remove(int index)
{
//not sure how to implment this becuase each element has to be a number.
}
int IntVector::at(int index)
{
return array[index];
}
void IntVector::pop()
{
num_elements = num_elements-1; //not really removing it from the "vector" but it won't print out again
}
void IntVector::at(int index, int val)
{
array[index] = val;
}
void IntVector::print()
{
for (int i = 0 ; i < num_elements; i++)
{
cout << array[i] << " ";
}
cout << endl;
}
IntVector::~IntVector()
{
delete[] array;
}
output
5 5 5 5 5
5 5 5 5 5
Hopefully, the comments help. I changed the name of the functions to better match the actual vecter class the already exists in C++. I think it's good to pick apart already defined functions like this because you get a better understanding of how they actually work and not just how to use them.
If you got any questions just leave a comment
In the class constructor, I am initializing other objects and pushing these objects to my class vector member. From what I understand, the vector create a copy of the object and stores it so that it doesn't go out of scope. However, when verifying the objects in another class function, they are not initialized anymore. Here's a example code to explain the behaviour:
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
class Square {
private:
int size_ = 0;
int colour_ = 0;
public:
Square(){
size_ = 0;
colour_ = 0;
}
void init(int size, int colour) {
size_ = size;
colour_ = colour;
}
int get_size() { return size_; }
};
class SetSquares {
private:
std::vector<Square> squares_;
int number_;
public:
SetSquares(): number_(0) {}
void init(int num) {
number_ = num;
squares_.clear();
squares_.resize(num);
for (int i=0; i < num; i++) {
Square square;
square.init(i, i);
squares_.push_back(square);
}
}
void sample(int i) {
if (i >= number_) { return; }
std::cout << "Square size is: " << squares_[i].get_size() << std::endl;
}
};
int main()
{
SetSquares set_of_squares;
set_of_squares.init(7);
set_of_squares.sample(4);
return 0;
}
resize(n) will create n default constructed elements in a vector and push_back will append new elements after those n elements. Use reserve and push_back or resize and index operator as suggested in comment.
I'm using C++ and am trying to set an array element values with a setter method. The array is a class private member:
class Boo{
private:
int *x;
public:
Boo();
~Boo();
void setX(int,int);
int getX(int);
}
Boo::Boo(){
x = new int[1];
x = 0;
}
void Boo::setX(int value, int index){
//set condition for NULL
x[index] = value;
}
int Boo::getX(int index){
if(x[index] == NULL) {cout<<"invalid index"<<end; return;}
return x[index];
}
void test(){
Boo *p = new Boo();
p->setX(12,0);
cout<<p->getX(0)<<endl;
}
I been trying to test setting the values in 'x' starting with index '0' (like test()) but it crashes. I wanted to write a program where I run a loop counting up, and I set the array values. Can this be accomplish this way?
Do not use new in C++!
In this case, you should use std::vector<int>.
If you want to fix your code unless use std::vector,
#include <cstddef>
#include <iostream>
#include <stdexcept>
#include <memory>
using std::size_t;
class Boo {
private:
int *x;
size_t size;
size_t capacity;
public:
Boo();
~Boo();
void setX(int,size_t);
int getX(size_t);
};
Boo::Boo() : size(), capacity(1) {
this->x = new int[1];
//x = 0;//DO NOT ASSIGN NULL POINTER!!!!
}
Boo::~Boo() noexcept {
delete[] x;
}
void Boo::setX(int value, size_t index){
if(this->capacity <= index) throw std::out_of_range("Boo::setX");//YOU MUST CHECK RANGE
this->x[index] = value;
++this->size;
}
int Boo::getX(size_t index){
if(this->size <= index) throw std::out_of_range("Boo::getX");//YOU MUST CHECK RANGE
return x[index];
}
void test(){
auto p = std::make_unique<Boo>();
p->setX(12,0);
std::cout << p->getX(0) << std::endl;
}
int main(){
test();
}
http://melpon.org/wandbox/permlink/aIhwC5c9o1q8ygIo
Boo::Boo()
{
x = new int[1];
x = 0;
}
you are not able to set value in an array because after initializing with memory, you have set the pointer of an array to null in constructor.
please use x[0] = 0; instead of x = 0;
I'm getting a weird problem in memory deallocation.
I have the following code for class MemoryPartition:
#include <cstring>
#include <iostream>
#include "memorypartition.h"
MemoryPartition::MemoryPartition(int maxSize) {
this->partitionArray = new char[maxSize];
memset(this->partitionArray, ((int) '$'), maxSize);
this->maxSize = maxSize;
this->isFree = true;
}
MemoryPartition::~MemoryPartition() {
delete[] this->partitionArray;
this->partitionArray = NULL;
maxSize = 0;
}
void MemoryPartition::setFree(bool isFree) {
this->isFree = isFree;
}
bool MemoryPartition::getFree() {
return this->isFree;
}
int MemoryPartition::getMaxSize() {
return this->maxSize;
}
void MemoryPartition::getPartitionArray() {
for(int i = 0;i < maxSize;i++) {
std::cout << partitionArray[i] << ' ';
}
std::cout << std::endl;
}
and the following code for MemoryManager:
#include "memorymanager.h"
#include <iostream>
#include <cstdlib>
MemoryManager::MemoryManager() {
}
MemoryManager::~MemoryManager() {
memory.clear();
}
void MemoryManager::defmem(int bytes) {
MemoryPartition *memPartition;
int maxMemorySize = bytes;
while(maxMemorySize != 0) {
int partitionSize = this->randomPartitionSize(maxMemorySize);
memPartition = new MemoryPartition(partitionSize);
this->memory.push_back(*memPartition);
std::cout << memPartition->getMaxSize() << std::endl;
memPartition->getPartitionArray();
maxMemorySize -= partitionSize;
delete memPartition;
memPartition = NULL;
}
}
int MemoryManager::randomPartitionSize(int maxSize) {
int value;
srand(time(NULL));
value = (rand() % maxSize) + 1;
return value;
}
and I'm getting a weird at delete[] in MemoryPartition destructor. Valgrind is telling me there are 13 frees and 10 allocs, but I can't see a reason why this delete[] would be called 3x.
Anyone see the problem I couldn't figure out?
Thanks in advance.
[]'s,
Its impossible to tell from the code above.
But my guess is that you need to define the copy constructor and assignment operator.
See Rule of 4 (Google/Wiki it).
Try the following:
class MemoryPartition
{
// Just add these two lines (keep them private)
MemoryPartition(MemoryPartition const&); // Don't define.
MemoryPartition& operator=(MemoryPartition const&); // Don't define.
<CLASS STUFF AS BEFORE>
};
Compile the code now. If it fails because the above are private then you have accidentally made a copy of the object somewhere and are doing a double delete on the pointer.