Initialized in a function and is not initialized in main - c++

I am trying to allocate memory in a function and I am not sure what I am doing wrong.
I want this:
int main()
{
int* test= 0;
initialize(test, 10);
int test2 = test[2];
delete[] test;
}
void initialize(int* test, int count)
{
test = new int[count];
for (int i = 0; i < count; i++)
{
test[i] = i;
}
}
But I receive this error: Unhandled exception at 0x770d15de in Robust Simulation.exe: 0xC0000005: Access violation reading location 0x00000008.
It breaks on line: int test2 = test[2];
but this works:
int main()
{
int* test=0;
test = new int[10];
for (int i = 0; i < 10; i++)
{
test[i] = i;
}
int test2 = test[2];
delete[] test;
}
Is there a scoping problem? I thought since I pass it a pointer it would be allocated and I would be able to access it outside of the initialize function.
Thanks for your help

Do following changes:-
initialize(&test, 10);
....
void initialize(int** test, int count)
{
*test = new int[count];
for (int i = 0; i < count; i++)
{ (*test)[i] = i; }
}
C++ has another feature called references if you want as it is :-
void initialize(int*& test, int count)
{
test = new int[count];
for (int i = 0; i < count; i++)
{ test[i] = i; }
}
what you are doing is passing the test[from main](address will pass) and storing in another local pointer variable named test.This new variable has lifetime of function scope and will get soon deleted leaving garbage after the completion of function.
Another option is
int* test= initialize(test, 10);
and change initialize as
int* initialize(int* test, int count)
{
test = new int[count];
for (int i = 0; i < count; i++)
{ test[i] = i; }
return test;
}

Pointers are also passed by value. You need:
void initialize(int*& test, int count)
Your version doesn't change the original pointer:
void initialize(int* test, int count)
{
//test is a copy of the pointer because it was passed by value
//...
}
After this, it's obvious why the delete[] fails - because the original pointer in main is never initialized.

You need to pass a reference to a pointer into your initialise function. Change the prototype to
void initialize(int* &test, int count)
The return value of new is assigned to that copy of the pointer that gets created when passing by value. So when the function exits, that address is lost as the copy goes out of scope and so you have a memory leak. Thus your test pointer never actually points to any allocated memory and so deleting it gives you an access violation.
Passing by reference allows the test pointer to be modified by the function

Related

Wrong answer from class member function when using template with class in c++?

I am trying to implement a class template for an Array class that should provide a method to count elements equal to a given element, but I get wrong results. This is my code:
main.cpp
#include <iostream>
#include "array.h"
int main() {
int arr[] = {1, 2, 3, 2, 5, 2};
char brr[] = {'a', 'b', 'c', 'd', 'a'};
Array<int> A(arr, 6);
Array<int> B(0, 7);
Array<char> C(brr, 5);
std::cout << A.getCount(2) << std::endl;
std::cout << B.getCount(0) << std::endl;
std::cout << C.getCount('a') << std::endl;
return 0;
}
array.h
template <typename T> class Array {
private:
T* ptrStart;
int size;
public:
Array() {
this->ptrStart = nullptr;
this->size = 0;
}
Array(T defaultValue, int size) {
T arr[size];
for (int i = 0; i < size; i++) arr[i] = defaultValue;
this->size = size;
this->ptrStart = arr;
}
Array(T* arr, int size) {
this->size = size;
this->ptrStart = arr;
}
int getCount(T);
};
template <typename T> int Array<T>::getCount(T element) {
int count = 0;
for (int i = 0; i < this->size; i++) if (this->ptrStart[i] == element) count++;
return count;
}
expected output:
3
7
2
actual output:
3
0
2
Both of these functions are invalid:
Array(T defaultValue, int size) {
T arr[size];
for (int i = 0; i < size; i++) arr[i] = defaultValue;
this->size = size;
this->ptrStart = arr;
}
Array(T* arr, int size) {
this->size = size;
this->ptrStart = arr;
}
The first function sets the data member ptrStart to a local variable arr that will not be alive after exiting the function.
The second function should dynamically allocate an array and copy elements from the array pointed to by arr.
For example, the second function can be defined the following way:
Array( const T *arr, int size) : ptrStart( new T[size] ), size( size ) {
for ( int i = 0; i < size; i++ )
{
ptrStart[i] = arr[i];
}
// or you can use standard algorithm std::copy
}
Also, you need to include a destructor and either make the class uncopyable or define at least the copy constructor and copy assignment operator.
This is an error
Array(T defaultValue, int size) {
T arr[size];
for (int i = 0; i < size; i++) arr[i] = defaultValue;
this->size = size;
this->ptrStart = arr;
}
The array arr only exists in the constructor. When the constructor exits the array no longer exists. But ptrStart is pointing to this array even after it has been destroyed. So you get unpredictable results.
In C++ you must always think about the lifetime of objects. Objects don't keep existing just because a pointer is pointing at them (this is different in some other languages). If you have a pointer pointing at an object which no longer exists, that is called a dangling pointer. In your code ptrStart is a dangling pointer (when you use this particular constructor).
Also T arr[size]; is not legal C++ since in C++ array sizes must be compile time constants and size is a variable.
Array(T defaultValue, int size) {
T arr[size];
for (int i = 0; i < size; i++) arr[i] = defaultValue;
this->size = size;
this->ptrStart = arr;
}
Here you set ptrStart to point at the local variable in a function. Once that function is done, the pointer is dangling and you have Undefined Behavior. Your program might crash, format your hard drive, output one or more wrong values or, possibly, output the right value.
Your constructor
Array(T defaultValue, int size) {
T arr[size];
for (int i = 0; i < size; i++) arr[i] = defaultValue;
this->size = size;
this->ptrStart = arr;
}
has at least 2 problems.
First T arr[size] is not standard C++ but uses a compiler extension. Also it is a local variable and this->ptrStart = arr; only assigns its adress to the member. Note that arr is an array, not a pointer, but it can decay to a pointer.
The problem lies in this function:
Array(T defaultValue, int size) {
T arr[size]; // Create array on stack - it will be deleted when the function returns
for (int i = 0; i < size; i++) arr[i] = defaultValue;
this->size = size;
this->ptrStart = arr; // Storing address to array which won't exist after this line
}
After the function returns the pointer this->ptrStart points to some random place in memory and at the point when you call B.getCount(0), it can be pretty much any data in there. Reading memory pointed by that dangling pointer is an Undefined Behavior. If you are unlucky, this can even cause a runtime exception, not only wrong result. (Or maybe it is lucky, at least the result isn't wrong ;) )
To fix that problem, you should use operator new to create the array. This way, the array will be created on heap instead of stack.
T arr[size]; // bad
T *arr = new T[size]; // good
Heap is not cleared when function returns.
This mean it is safe to use array from heap outside of the function it was created in.
Unfortunately, it also mean you need to delete it manually in the destructor of Array.
~Array() {
if (createdInConstructor)
delete[] this->ptrStart;
}
createdInConstructor is a new bool field of the class so the destructor don't try to delete the array in case of objects A & C.
You could also use a smart pointer to achieve that a little easier.

Cannot access global array in main after initializing in another function

I'm having a hard time understanding why I cannot access my global 2D array in my main function after I have initialized it already in another function.
EDIT: Forgot to specify that d is a known int variable declared before all of this, usually 3 or 4.
void init();
int **board;
int main(){
init();
cout << board[0][0];
}
void init(){
int **board = new int*[d];
for (int i = 0; i < d; i++){
board[i] = new int[d];
}
int n=d*d;
for (int i = 0; i < d; i++){
for (int j = 0; j < d; j++){
board[i][j] = n;
n--;
}
}
So the moment I try to access board[0][0] in main() I get an "Access violation at 0x00000000".
I enter debugging and see that board[0][0] points to 0x000000 when being called in main() but if I try to call it in the init() function, at the end for example, it works perfectly and I can access any variable.
You're creating a new temporary variable:
int **board = new int*[d];
This is a memory leak and you cannot access the memory after the function. You can just do this:
board = new int*[d]; //remember to delete []!
I see you have tagged your question [c++]. If this is the case, you should be using the standard library instead of dealing with raw pointers. std::vector and std::array come to mind.
void init(){
int **board = new int*[d];
Here, you are defining a local variable board in the function which blocks the global variable board.
Instead, assign the value directly, don't define another variable:
void init(){
board = new int*[d];

C++ pointer to int in loops?

Ok, so I'm quite new to C++ and I'm sure this question is already answered somewhere, and also is quite simple, but I can't seem to find the answer....
I have a custom array class, which I am using just as an exercise to try and get the hang of how things work which is defined as follows:
Header:
class Array {
private:
// Private variables
unsigned int mCapacity;
unsigned int mLength;
void **mData;
public:
// Public constructor/destructor
Array(unsigned int initialCapacity = 10);
// Public methods
void addObject(void *obj);
void removeObject(void *obj);
void *objectAtIndex(unsigned int index);
void *operator[](unsigned int index);
int indexOfObject(void *obj);
unsigned int getSize();
};
}
Implementation:
GG::Array::Array(unsigned int initialCapacity) : mCapacity(initialCapacity) {
// Allocate a buffer that is the required size
mData = new void*[initialCapacity];
// Set the length to 0
mLength = 0;
}
void GG::Array::addObject(void *obj) {
// Check if there is space for the new object on the end of the array
if (mLength == mCapacity) {
// There is not enough space so create a large array
unsigned int newCapacity = mCapacity + 10;
void **newArray = new void*[newCapacity];
mCapacity = newCapacity;
// Copy over the data from the old array
for (unsigned int i = 0; i < mLength; i++) {
newArray[i] = mData[i];
}
// Delete the old array
delete[] mData;
// Set the new array as mData
mData = newArray;
}
// Now insert the object at the end of the array
mData[mLength] = obj;
mLength++;
}
void GG::Array::removeObject(void *obj) {
// Attempt to find the object in the array
int index = this->indexOfObject(obj);
if (index >= 0) {
// Remove the object
mData[index] = nullptr;
// Move any object after it down in the array
for (unsigned int i = index + 1; i < mLength; i++) {
mData[i - 1] = mData[i];
}
// Decrement the length of the array
mLength--;
}
}
void *GG::Array::objectAtIndex(unsigned int index) {
if (index < mLength) return mData[index];
return nullptr;
}
void *GG::Array::operator[](unsigned int index) {
return this->objectAtIndex(index);
}
int GG::Array::indexOfObject(void *obj) {
// Iterate through the array and try to find the object
for (int i = 0; i < mLength; i++) {
if (mData[i] == obj) return i;
}
return -1;
}
unsigned int GG::Array::getSize() {
return mLength;
}
I'm trying to create an array of pointers to integers, a simplified version of this is as follows:
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
Now the problem is that the same pointer is used for j in every iteration. So after the loop:
array[0] == array[1] == array[2];
I'm sure that this is expected behaviour, but it isn't quite what I want to happen, I want an array of different pointers to different ints. If anyone could point me in the right direction here it would be greatly appreciated! :) (I'm clearly misunderstanding how to use pointers!)
P.s. Thanks everyone for your responses. I have accepted the one that solved the problem that I was having!
I'm guessing you mean:
array[i] = &j;
In which case you're storing a pointer to a temporary. On each loop repitition j is allocated in the stack address on the stack, so &j yeilds the same value. Even if you were getting back different addresses your code would cause problems down the line as you're storing a pointer to a temporary.
Also, why use a void* array. If you actually just want 3 unique integers then just do:
std::vector<int> array(3);
It's much more C++'esque and removes all manner of bugs.
First of all this does not allocate an array of pointers to int
void *array = new void*[2];
It allocates an array of pointers to void.
You may not dereference a pointer to void as type void is incomplete type, It has an empty set of values. So this code is invalid
array[i] = *j;
And moreover instead of *j shall be &j Though in this case pointers have invalid values because would point memory that was destroyed because j is a local variable.
The loop is also wrong. Instead of
for (int i = 0; i < 3; i++) {
there should be
for (int i = 0; i < 2; i++) {
What you want is the following
int **array = new int *[2];
for ( int i = 0; i < 2; i++ )
{
int j = i + 1;
array[i] = new int( j );
}
And you can output objects it points to
for ( int i = 0; i < 2; i++ )
{
std::cout << *array[i] << std::endl;
}
To delete the pointers you can use the following code snippet
for ( int i = 0; i < 2; i++ )
{
delete array[i];
}
delete []array;
EDIT: As you changed your original post then I also will append in turn my post.
Instead of
Array array = Array();
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject(&j);
}
there should be
Array array;
for (int i = 0; i < 2; i++) {
int j = i + 1;
array.addObject( new int( j ) );
}
Take into account that either you should define copy/move constructors and assignment operators or define them as deleted.
There are lots of problems with this code.
The declaration void* array = new void*[2] creates an array of 2 pointers-to-pointer-to-void, indexed 0 and 1. You then try to write into elements 0, 1 and 2. This is undefined behaviour
You almost certainly don't want a void pointer to an array of pointer-to-pointer-to-void. If you really want an array of pointer-to-integer, then you want int** array = new int*[2];. Or probably just int *array[2]; unless you really need the array on the heap.
j is the probably in the same place each time through the loop - it will likely be allocated in the same place on the stack - so &j is the same address each time. In any case, j will go out of scope when the loop's finished, and the address(es) will be invalid.
What are you actually trying to do? There may well be a better way.
if you simply do
int *array[10];
your array variable can decay to a pointer to the first element of the list, you can reference the i-th integer pointer just by doing:
int *myPtr = *(array + i);
which is in fact just another way to write the more common form:
int *myPtr = array[i];
void* is not the same as int*. void* represent a void pointer which is a pointer to a specific memory area without any additional interpretation or assuption about the data you are referencing to
There are some problems:
1) void *array = new void*[2]; is wrong because you want an array of pointers: void *array[2];
2)for (int i = 0; i < 3; i++) { : is wrong because your array is from 0 to 1;
3)int j = i + 1; array[i] = *j; j is an automatic variable, and the content is destroyed at each iteration. This is why you got always the same address. And also, to take the address of a variable you need to use &

C++ Accessing Values at pointer of 2D Array

I need a dynamic 2D array of ints, it will represent a standard matrix. The size and elements are read in from a file at runtime.
Taking direction from other stack posts I've setup my array as follows;
void buildArray(ifstream &file, int** 2dArray);
void buildQueue(Queue<int> &Q, int** 2dArray);
int main()
{
int** 2dArray;
Queue<int> Q;
//...
// open file
//...
buildMatrix(file, 2dArray)
buildQueue(Q, 2dArray)
}
void buildArray(ifstream &file, int** 2dArray)
{
int size, element;
while (file.good()) {
file >> size;
2dArray = new int*[size];
for (int i = 0; i < size; i++)
2dArray[i] = new int[size];
// now I should be able to use 2dArray[r][c]
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
file >> element;
2dArray[i][j] = element;
}
}
}
Then I need to read the ints stored at each position [r][c] and build a queue. I think my problem is dereferencing the pointers... but I'm not sure.
void buildQueue(Queue<int> &Q, int** 2dArray)
{
int row, column, element;
// size is passed in as well, size is our rows or columns size here
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
row = i;
column = j;
element = 2dArray[i][j]; // getting seg fault here!
Q.push_back(row, column, element);
}
}
}
I should add that I know I could use vectors. I'm challenging myself here to responsibly build, use and deallocate a 2D array using pointers.
What is table?
table = new int*[size];
Shouldn't this be
2dArray = new int*[size];
Also return the pointer from the function
Change
void buildArray(ifstream &file, int** 2dArray)
to
int ** buildArray(ifstream &file)
because otherwise buildArray gets a copy of the variable. And this copy now holds the pointer to the allocated memory. The pointer in the calling function never gets updated.
In your original code add a printf 2dArray before and after the buildArray call.
printf("%p, 2dArray);
buildMatrix(file, 2dArray);
printf("%p, 2dArray);
You will see that 2dArray doesn't change. So you are essentially passing an uninitialized
pointer to buildQueue.
buildArray and call should be changed like this
void buildArray(ifstream &file, int** arr)
{
int size, element;
while (file.good()) {
file >> size;
arr = new int*[size];
for (int i = 0; i < size; i++)
arr[i] = new int[size];
for (int i = 0; i < size; i++) {
for (int j = 0; j < size; j++) {
file >> element;
arr[i][j] = element;
}
}
}
return arr;
}
int main()
{
int** 2dArray;
Queue<int> Q;
//...
// open file
//...
2dArray = buildMatrix(file);
buildQueue(Q, 2dArray);
}
If you are allocating the initial array inside a function, you either need to pass it as a triple pointer and change to:
*2dArray = new int*[size],
or return an int**
Otherwise you will lose the pointer to your new memory.
Don't forget, pointers are passed by value. As is, after your buildArray() call, you still will not have a pointer to valid memory.
When you allocate in a function a pointer passed in argument you only change the copy value. In C/C++ when you send a parameter to a function a copy of this is create. So, like the other answers hasaid before, it's possible to return the new value of the pointer changing your void buildArray(...) to int** buildArray(...) or sending a pointer on your pointer (it's look difficult), or finally, you're in C++ so you can send a reference, void buildArray(ifstream &file, int**& 2dArray) also 2dArray will be the real pointer from the main and you should change his value without changing your code.

Unitialized local variable and help correcting

I am learning about pointers and the new operator in class.
In my readArray function I am to read in a size. Use the size to dynamically create an integer array. Then assign the array to a pointer, fill it, and return the size and array.
I believe I've gotten that part corrected and fixed but when I try to sort the array, i get the error "uninitialized local variable temp used."
The problem is though I get that error when I am trying to intialize it.
Any help appreciated thank you. Seeing my errors is very helpful for me.
#include <iostream>
using namespace std;
int* readArray(int&);
void sortArray(int *, const int * );
int main ()
{
int size = 0;
int *arrPTR = readArray(size);
const int *sizePTR = &size;
sortArray(arrPTR, sizePTR);
cout<<arrPTR[1]<<arrPTR[2]<<arrPTR[3]<<arrPTR[4];
system("pause");
return 0;
}
int* readArray(int &size)
{
cout<<"Enter a number for size of array.\n";
cin>>size;
int *arrPTR = new int[size];
for(int count = 0; count < (size-1); count++)
{
cout<<"Enter positive numbers to completely fill the array.\n";
cin>>*(arrPTR+count);
}
return arrPTR;
}
void sortArray(int *arrPTR, const int *sizePTR)
{
int *temp;
bool *swap;
do
{
swap = false;
for(int count = 0; count < (*sizePTR - 1); count++)
{
if(arrPTR[count] > arrPTR[count+1])
{
*temp = arrPTR[count];
arrPTR[count] = arrPTR[count+1];
arrPTR[count+1] = *temp;
*swap = true;
}
}
}while (swap);
}
You make temp an int pointer (uninitiialized), and then set the thing it points at (anything/nothing) to arrPTR[ccount]. Since you are using temp only to swap, it should be the same type as those being swapped, in this case: an int.
If it absolutely must be a pointer (there is no good reason for this, it's slow, confusing, adds potential for errors, and adds potential for memory leaks):
int *temp = new int; //make an int for the pointer to point at
bool *swap = new bool; //make an bool for the pointer to point at
do
{
//your code
}while (swap);
delete temp;
delete swap;
You declared temp as a pointer. You need to allocate it on the heap before dereferencing and assigning to it later. However perhaps a variable on the stack would be preferable?
FYI: You should be aware of the memory leak in readArray as well which is leaving callers responsible for calling delete []
Edit: I hope this will help clear up some of the other problems.
#include <iostream>
int* readArray(int&);
void sortArray(int*, int);
int main ()
{
int size(0); // use stack when possible
int *arrPTR = readArray(size);
sortArray(arrPTR, size);
// arrays are zero based index so loop from 0 to size
for (int index(0); index < size; ++index)
std::cout << arrPTR[index];
delete [] arrPTR; // remember to delete array or we have a memory leak!
// note: because we did new[] for an array we match it with delete[]
// if we just did new we would match it with delete
system("pause");
return 0;
}
int* readArray(int& size)
{
std::cout << "Enter a number for size of array.\n";
std::cin >> size;
int *arrPTR = new int[size]; // all news must be deleted!
// prefer pre-increment to post-increment where you can
for(int count(0); count < size; ++count)
{
std::cout << "Enter positive numbers to completely fill the array.\n";
std::cin >> arrPTR[count];
}
return arrPTR;
}
// passing size by value is fine (it may be smaller than pointer on some architectures)
void sortArray(int *arrPTR, int size)
{
// you may want to check if size >= 2 for sanity
// we do the two loops to avoid going out of bounds of array on last iteration
for(int i(0); i < size-1; ++i) // the first to compare (all except last)
{
for(int j(i+1); j < size; ++j) // the second to compare (all except first)
{
// do comparison
if (arrPTR[i] > arrPTR[j]) // from smallest to biggest (use < to go from biggest to smallest)
{
// swap if needed
int temp(arrPTR[i]); // put this on stack
arrPTR[i] = arrPTR[j];
arrPTR[j] = temp;
}
}
}
}
temp is a "pointer to int, which you're not initializing. When you say *temp = ... you're actually assigning to whatever temp happens to be pointing, but since you haven't told it what to point to, it can write pretty much anywhere in the address space of your program.
Because of the way you're using them, it seems that temp and swap shouldn't be pointers at all, just a plain int and bool.
You didn't initialize the temp pointer do when you dereference it you are writing to a random part of memory. Temp doesn't need to be a pointer, it can just be an int. Just replace EVERY instance of *temp with temp.