Adding two array objects with operator overloading resulting in segmentation fault - c++

I'm setting up a class in c++ that will have array objects and a function to add them together (by adding their individual components). Each of these objects has a pointer to a 'new' array of floats which will be added together. I believe that either because these are pointers or are assigned to 'new' arrays, there is some sort of memory issue when accessing their components through the overloaded + operator, but I'm not sure what specifically is the issue. The file compiles without any issues but simply says "Segmentation fault (core dumped)" when run. Also I'm aware I should be using a min value rather than max in the for loop but right now all my arrays are the same size so I'm just testing it this way.
If I comment out the actual addition of the arrays in main(), the error message completely disappears, but I'm not quite sure why.
#include <iostream>
using namespace std;
class Array
{
private:
int size, location;
float value;
public:
float *arrayptr;
Array(int size)
{
arrayptr = new float[size];
}
void setValue(int location, float value)
{
arrayptr[location] = value;
}
Array operator+(Array a)
{
int max;
if (a.size >= size)
{
max = a.size;
}
else
{
max = size;
}
Array tmparray(max);
for(int i=0; i<max; i++)
{
tmparray.arrayptr[i] = a.arrayptr[i] + arrayptr[i];
}
return tmparray;
}
};
main()
{
Array a1(3);
a1.setValue(0, 1.0);
a1.setValue(1, 22.0);
a1.setValue(2, 12.2);
Array a2(3);
a2.setValue(0, 3.3);
a2.setValue(1, 44.5);
a2.setValue(2, 21.7);
Array tmp(3);
// Source of the error (parenthesis doesn't seem to affect it):
tmp = (a1 + a2);
}

You don't set size in the constructor, so when if (a.size >= size) happens, you get undefined behavior. Probably gets set to some ludicrous value and you walk off the array.
m_size = size Set the member size value to the size value passed into the constructor.
The + operator also doesn't watch out for walking off the array when the arrays are not the same size.

You had not Initialize size variable.
You need to Initialize it.
Array(int _size)
{
size = _size;
arrayptr = new float[size];
}
And your size variable is private.
So, it can't reference. So size variable need to declare as public.

Related

Helper function to construct 2D arrays

Am I breaking C++ coding conventions writing a helper function which allocates a 2D array outside main()? Because my application calls for many N-dimensional arrays I want to ensure the same process is followed. A prototype which demonstrates what I am doing :
#include <iostream>
// my helper function which allocates the memory for a 2D int array, then returns its pointer.
// the final version will be templated so I can return arrays of any primitive type.
int** make2DArray(int dim1, int dim2)
{
int** out = new int* [dim1];
for (int i = 0; i < dim2; i++) { out[i] = new int[dim2];}
return out;
}
//helper function to deallocate the 2D array.
void destroy2DArray(int** name, int dim1, int dim2)
{
for (int i = 0; i < dim2; i++) { delete[] name[i]; }
delete[] name;
return;
}
int main()
{
int** test = make2DArray(2,2); //makes a 2x2 array and stores its pointer in test.
//set the values to show setting works
test[0][0] = 5;
test[0][1] = 2;
test[1][0] = 1;
test[1][1] = -5;
// print the array values to show accessing works
printf("array test is test[0][0] = %d, test[0][1] = %d, test[1][0] = %d, test[1][1] = %d",
test[0][0],test[0][1],test[1][0],test[1][1]);
//deallocate the memory held by test
destroy2DArray(test,2,2);
return 0;
}
My concern is this may not be memory-safe, since it appears I am allocating memory outside of the function in which it is used (potential out-of-scope error). I can read and write to the array when I am making a single small array, but am worried when I scale this up and there are many operations going on the code might access and alter these values.
I may be able to sidestep these issues by making an array class which includes these functions as members, but I am curious about this as an edge case of C++ style and scoping.
There is a difference between allocating 2D arrays like this and what you get when you declare a local variable like int ary[10][10] that based on your statement
My concern is that this operation may not be memory-safe, since it
appears that I am allocating memory for an array outside of the
function in which it is used (potential out-of-scope error)
I am guessing you do not fully understand.
You are allocating arrays on the heap. Declaring a local variable like int ary[10][10] places it on the stack. It is the latter case where you need to worry about not referencing that memory outside of its scope-based lifetime; that is, it is the following that is totally wrong:
//DON'T DO THIS.
template<size_t M, size_t N>
int* make2DArray( ) {
int ary[M][N];
return reinterpret_cast<int*>(ary);
}
int main()
{
auto foo = make2DArray<10, 10>();
}
because ary is local to the function and when the stack frame created by the call to make2DArray<10,10> goes away the pointer the function returns will be dangling.
Heap allocation is a different story. It outlives the scope in which it was created. It lasts until it is deleted.
But anyway, as others have said in comments, your code looks like C not C++. Prefer an std::vector<std::vector<int>> rather than rolling your own.
If you must use an array and are allergic to std::vector, create the 2d array (matrix) as one contiguous area in memory:
int * matrix = new int [dim1 * dim2];
If you want to set the values to zero:
std::fill(matrix, (matrix + (dim1 * dim2)), 0);
If you want to access a value at <row, column>:
int value = matrix[(row * column) + column];
Since the matrix was one allocation, you only need one delete:
delete [] matrix;

C++ Dynamic Array allocation in Classes

I am currently learning basics of c++, and am coming across an issue with the class array below.
class Arrayclass {
private:
int arraySize;
float array[];
public:
Arrayclass(int arraySize) {
float * array = new float[arraySize]();
}
~Arrayclass() {
delete[] array;
}
}
As far as I am aware, I am having issues with the array being initialized in the constructor not actually corresponding to a stored array in the new class, thus when I am initializing a new class in my main, the array created holds 0 values. I apologize my explanation is unclear, just trying to understand how the array initialized in the constructor correlates to the array in my private.
float array[]
either is an extension or just doesn't compile. For a C-style static array, Type name[constexpr_size] is used. For a dynamic array, Type* name is stored as a pointer to the beginning of the storage allocated.
Dynamic Array
OK, we need the second option. Then, we start with your snippet
class Array { // "class Arrayclass" -> "class Array", no need to repeat ourselves
private:
float* array{};
int size{}; // "Array::arraySize" -> "Array::size", again
public:
~Array() { delete[] array; } // your destructor is fine
};
(see member initializer as an explanation to those {} initializers in float* array{} and int size{}).
What about
Arrayclass(int arraySize) { float * array = new float[arraySize](); }
, you create a local float* which dies at the end of scope (=the constructor). You probably meant to store that newly allocated array in (this->)array:
Array(int newSize) { // BAD CODE, see below
array = new float[newSize]{};
size = newSize;
}
but the code above is like writing float* p; p = something (create default, than initialize it) instead of float* p{something} (initialize on creation), let's improve it by using member initializer list:
Array(int newSize): array{new float[newSize]{}}, size{newSize} {}
Now, your array (almost) can construct and destruct properly.
==========
However, there's still an issue left: code such as
{
Array a1{42};
Array a2{a1}; // copy construction
}
has undefined behavior and in practice (in this case) should/might crash your application. Why? Because it works as something like (sizes omitted):
{
float* array1{new float[42]{}};
float* array2{array1};
delete[] array1;
delete[] array2; // that UB (double free); the same dynamic array is deleted twice
}
Well, it is a topic for another "lesson". See the rule of three (five) (zero). In general, see RAII and copy/move-semantics.

C++ Set 2d array sizes of class member array in constructor

I only found solutions for 1d arrays, but couldn't apply them to 2d arrays.
The possible solutions included "vectors", "templates", and "pointers to arrays".
I know I can get vectors to work, but I would rather use either of the other 2. Preferably templates because I don't want to manually destruct, but pointers work too. (the pointer would be pointed to an array created in the constructor).
The class contains an empty 2d array called screen. The constructor is supposed to set its size. I tried too many things for me to list them all here, but I'll show what I currently have. (last thing i tried were pointers to arrays created in the constructor. in this case screen was a char pointer)
Screen::Screen(const int w, const int h) : screen(new char[h][w]) {} {
width = w;
height = h;
}
array size in new-expression must be constant
I failed implementing either of those strategies and received many kinds of errors while trying to make it work. How would I solve this problem? (primarily I want to know how to do this with templates. if not possible then with pointers to arrays created in the constructor)
The question was a little ambiguous, but it sounds like you want to dynamically allocate an array given some input.
Edit I changed the answer to match the code you provided. This creates a 2d array of chars given the height and width.
class Screen {
private:
char **data;
int rows;
int columns;
public:
Screen(int num_rows, int num_cols);
};
Screen::Screen(int num_rows, int num_cols) {
data = new char * [num_rows];
for (int i = 0; i < num_rows; ++i) {
data[i] = new char[num_cols];
}
rows = num_rows;
columns = num_cols;
}
This creates an empty 2D array of chars.
Explanation: All arrays in c are just pointers to the first block in memory of the type you have declared. By having the member variable as double pointer, you have an array of char pointers, which each point to the first value in each of their respective arrays.
BUT be careful, you WILL need to free the data variable to avoid memory leaks, by declaring a destructor.
Screen::~Screen() {
for (int i = 0; i < rows; ++i) {
delete[] data[i];
}
delete[] data;
}

Infinite size Stack implementation using pointer to an array

I have been trying to make a infinite size stack using pointer to any int:
//in class:
int* stack;
//In constructor:
stack = new int();
//In deconstructor:
delete stack;
//In Push:
stack(++top) = element;
Is this declaration correct? Can I use this to make an infinite size stack? I run into error when I try to put elements into the stack using such pointer declaration.
It seems you are writing codes in C++? If no, please just ignore my post(face palm).
Firstly, the memory that could be assigned to a program is limited, i.e. no infinite size stack. In C++, there is BSS, Stack and Heap memory. In your case, you have used new operator to assign memory. This in fact effectively means you would like to get a piece of memory in the heap to store your value. Though the size of heap could be dynamically extended, its memory size is still not infinite.
Moreover, it seems what you would like to do in the constructor is to build up an int array with unlimited size. In fact, to declare an array, you may write new int[arraySize] to declare an int array of size, arraySize, in the heap. However, what you have written here is allocating a single int in the heap since the brackets you used are not square, but round. Unfortunately, to create an array, you need to declare its size first (for more details, you may search for stack array and dynamic array). So as to get rid of the size problem, you may use other data structures like std::vector and so forth for simple.
int* stack;
stack = new int();
These 2 statements are to have a pointer pointing to a single int stored in heap memory. Therefore, currently, the stack you make seems to be only able to store an int only.
As for the push function, top is the index of the top int in the stack?
One more thing, in case, what you want to make is creating a pointer to point an int array, and use the array as a stack. Then, you may think about the way to add memory, and have the deconstructor revised to be like this:
delete[] stack;
If you find difficulty in understanding my above paragraphs and have interest in learning more, perhaps you may firstly learn about stack & heap, then, the array declaration as well as its relationship with the memory allocation, followed by the knowledge about pointers.
I am a newbie. Hopefully, I haven't made any mistake in my answer.
First of all new int () creates only a single int not an array of integers therefore you can't do something like stack(++top) = element;.
If you want to create a dynamic array you should use int* stack = new int[size] and delete it with delete [] stack. As you can see the array has a limited size of size but you can resize it when it becomes full. There is no built-in way to resize the array but you can create a new dynamic array with bigger size and copy the old array into it and then remove the old array. But again the stack won't have infinite size since your memory is limited. If the allocation fails an exception will be thrown.
Below is a simple implementation of stack based on a dynamic array.
#include <stdexcept>
using namespace std;
class Stack{
public:
Stack (int _size = 20){
size = _size;
topIndex = 0;
stack = new int [size];
}
~Stack (){
delete [] stack;
}
void resize(){
int new_size = size*2;
int * new_stack;
// try{
new_stack = new int[new_size];
// } catch (std::bad_alloc&) {
// unsuccessful allocation
// }
for ( int i=0; i<size; ++i ){
new_stack[i] = stack[i];
}
delete [] stack;
stack = new_stack;
size = new_size;
}
void push(int element){
if (topIndex + 1 == size){
resize();
}
stack[topIndex++] = element;
}
int top(){
if ( topIndex <= 0 ){
throw std::out_of_range("stack is empty");
} else {
return stack[topIndex-1];
}
}
void pop(){
if ( topIndex <= 0 ){
throw std::out_of_range("stack is empty");
} else {
--topIndex;
}
}
private:
int * stack;
int size;
int topIndex;
};
int main(){
Stack stk;
for ( int i=0;i<50;++i ){
stk.push(i);
cout << stk.top() << endl;
}
for ( int i=0;i<50;++i ){
stk.pop();
cout << stk.top() << endl;
}
}
Note that this is all just for practice and the above implementation is error prone. You should almost always use built-in data structures in practical situations.

A variable seems to be de-referencing when I use it in a dynamic array (C++)

Here we are once again good people of the internet.
This is the code I'm using:
//This is what is in the header file
int *myArr[]; // A two-dimensional array representing holding the matrix data
//This is what is in the definition file
Matrix::Matrix(int n, int m)
{
myRows = n;
myColumns = m;
initialize();
}
void Matrix::initialize()
{
*myArr = new int[myRows];
for (int i=0; i < 3; i++)//Only set to 3 since myRows is acting crazy
{
myArr[i] = new int[myColumns];
}
}
For some reason when I use myRows variable to create the myArr array it just seems to stop referencing the value it was pointing towards before.
For instance I give it the value 3 and after the *myArr = new int[myRows] has been executed it changes the value of myRows to 9834496, which I don't understand.
Does the "new" de-reference the variable or something?
Or am I doing something wrong?
Oh and since this is a school practice project (so I won't blame you if you don't answer) I would prefer an answer over working code, so that I could know what I did wrong for future projects.
int *myArr[];
This is wrong! You've to tell the compiler the size also, of your array of pointer. How about if you declare int a[]. You're telling the compiler to create an array of int, of unknown size, which is not allowed in C++. That is why you cannot do that.
I would suggest you to do this:
int **myArr;
void Matrix::initialize()
{
myArr = new int*[myRows]; //note int* here!
for (int i=0; i < myRows; i++)
{
myArr[i] = new int[myColumns];
}
}
This should work now.
Try replacing:
*myArr = new int[myRows];
by
myArr = new int*[myRows];
You should use std::vector<>. It deals with all the problems of memory allocation and deallocation.
And it does so without any bugs.
And then you focus yourself on the real goals of your algorithm. Not on memory management :-)
typedef std::vector<int> Ints;
typedef std::vector<Ints> Matrix;
Matrix myArray;
I'm not sure if you're project requires you to use multi-level pointers, if it doesn't another way you can approach this problem is to just treat the multi-dimensional array as one big flat array.
That means when you reach the end of a row, the index after that would be the first element of the next row. Here's how the code might look:
// In this approach the double pointer int**
// is replaced with just a simple int*
int *myArr;
// Here's your Matrix ctor. Note the use of the initializer list
Matrix::Matrix(int n, int m) : myRows(n), myColumns(m)
{
initialize();
}
void Matrix::initialize()
{
myArr = new int[myRows * myColumns];
/* This loop is no longer needed since we're allocating
one big chunk at once.
for (int i=0; i < 3; i++)//Only set to 3 since myRows is acting crazy
{
myArr[i] = new int[myColumns];
}
*/
}
// To retrieve stuff from your array
// you would do something like this:
int Matrix::operator() (const int x, const int y)
{
return myArr[x * myRows + y];
}