Array data being corrupted after passing pointer, C - c++

I'm dereferencing a pointer to my array struct in my function and printing it within the function. This works correctly, however, as soon as I return the pointer out of the function it prints incorrectly. I did some research on similar questions, but I just cannot seem to find my exact problem.
correct print: 11 5 1 2 3 4 5 10 20 30 40
incorrect: 11 5 1 2 5024 96 0 0 20 30 40
(Problem areas are in commented in CAPS)
[arraytools.cpp]
#include "arraytools.h"
#include <iostream>
using namespace std;
void DisplayArray (short int* a)
{
short int size = a[0];
int i;
for (i=0; i<size; i++)
{
cout<< a[i] << " ";
}
cout<<endl;
}
short int* ConcatArray (short int* a1, short int* a2)
{
short int size = a1[0] + a2[0] + 1; //size of newarray
short int *ptr; //pointer for newarray
short int newarray[size]; //initializing new array with given new size
newarray[0] = size; //making first object in new array the size of it
int i,j;
for (i=0; i<a1[0]; i++) //loop to store first array objects to newarray
{
newarray[i+1] = a1[i];
}
int lastpoint = a1[0] + 1; //marks the point to start adding the second array to newarray
for (j=0; j<a2[0]; j++) //loop to store second array objects to newarray
{
newarray[lastpoint] = a2[j];
lastpoint++;
}
ptr = &newarray[0]; //assigning new array to pointer
DisplayArray(ptr); //PRINTS CORRECTLY HERE
return ptr;
}
[main.cpp]
#include "arraytools.h"
#include <iostream>
using namespace std;
int main()
{
char choice = 'y'; //user defined later in program
while (choice == 'y') // for repeating process
{
//declaring two arrays of short int
short int arr1[] = {5,1,2,3,4};
short int arr2[] = {5, 10, 20, 30, 40};
//pointers to refer to declared arrays
short int* nptr, *ar1, *ar2;
ar1 =arr1;
ar2 =arr2;
DisplayArray(ar1);
DisplayArray(ar2);
nptr = ConcatArray(ar1, ar2); //RECIEVES RETURNED POINTER
DisplayArray(nptr); //PRINTS INCORRECTLY
cout<<"Run process again? y/n: "; //loop exit condition
cin >> choice;
}
return 0;
}

This line is root of problem:
short int newarray[size];
It allocates array in stack, and then you return address of that, even though it becomes invalid as soon as you return from that function. Try this:
short *newarray = new short [size];
Now it goes to heap. Of course you should also delete that with delete[] operator when you no longer need it, like maybe in main after printing:
delete[] nptr;

You are allocating newarray "on the stack". It will be reclaimed once it goes out of scope (i.e. function ends). Use malloc if you really want to do this. Or if you really are using C++ consider a better container such as std::vector.
ConcatArray (short int* a1, short int* a2)
{
short int size = a1[0] + a2[0] + 1; //size of newarray
short int *ptr; //pointer for newarray
short int newarray[size]; //initializing new array with given new size

When you put the new array as a variable local to the function, it is allocated on the stack (usually). Then you return a pointer to the calling code. But the memory is freed up once the method returns. So the pointer is pointing to an undefined area of memory once the called function returns.

Your function returns a pointer on a local variable wich is stored in stack. You need malloc memory for your data.

Related

What does int ** ptr (pointer to a pointer) as a C++ function argument mean?

I was asked to write a program that gets an array of integers arr, and its logical size. When called it creates a new array containing only the positive numbers from arr.
For example, if arr=[3, -1, -3, 0, 6, 4], the functions should create an array containing the following 3 elements: [3, 6, 4],
The specific function should be like this:
void getPosNums4 (int* arr, int arrSize,
int** outPosArrPtr, int* outPosArrSizePtr)
uses the pointer outPosArrPtr to update the base address of the array (containing the positive numbers), and the pointer outPosArrSizePtr to update the array’s logical size.
I was having difficulty understanding what does ** outPosArrPtr mean, as well as how to use it in both the main function and the function call. I am aware that my main function's cout will be the address in the memory of the new array, as well as the new array's size. Thank you.
#include <iostream>
using namespace std;
void getPosNums4(int* arr, int arrSize, int** outPosArrPtr, int* outPosArrSizePtr);
int main(){
int arr[8]= {3,-1,-3,0,6,4,-5,8};
int* inputPtr = arr;
int inputArrSize = 8;
int* outputArrSizePtr = new int;
int outputArrSize = 0;
outputArrSizePtr = &outputArrSize;
int* outPosArr = new int[outputArrSize];
int** outPosArrPtr = &outPosArr;
cout<<"Test function 4: "<<endl;
getPosNums4(inputPtr, inputArrSize, outPosArrPtr, outputArrSizePtr);
cout<<outPosArrPtr<<*outputArrSizePtr4<<endl;
return 0;
}
void getPosNums4(int* arr, int arrSize, int** outPosArrPtr, int* outPosArrSizePtr) {
for (int i = 0; i < arrSize; i++){
if (arr[i] > 0){
*outPosArrPtr[*outPosArrSizePtr] = arr[i];
*outPosArrSizePtr = *outPosArrSizePtr + 1;
}
}
}
int** outPosArrPtr is a pointer array, or alternatively a pointer to pointers. This is a common concept in C and I recommend The C Programming Language by Kernighan and Ritchie for further details.
To understand what's going on, first let's just look at the simpler pointer-to-int:
int *outPosArrPtr
In C, this pointer-to-int can be equivalent to an integer array:
int outPosArrPtr[]
But what about the second *?
-This means you have a pointer-to-pointer-to-int, which you can use as an array of pointers-to-int.
So the function void getPosNums4 itself does not create a new array that contains only positive numbers. Instead, it returns a pointer array with pointers that point to the memory location of only the positive numbers in the original input array int *arr.

Pointers array, deleting and asigning to it pointers in C++

My problem is when I declare an array int** arr =new* int[n] and I want to assign to it pointer to array and later change that pointer to a different pointer which is copy of it values + one other number ,it brakes down and appears (probably) infinite loop . Can you say how to do this in proper way using some low tools with c++/c or can you correct my code?
Additional explenation: the code is producing very simple output but it is not important. I want to create program to change in array pointer(int*arr) in specific index pointer to diffrent pointer . But additionally pointers direct first element in arrays .Also diffrennce beetween new and old array (which is changed in int**arr in index for example 0) is that new is bigger on a new element (int this case new number).So this output is only checking if it works.
Below is my whole code
#include <iostream>
using namespace std;
void stepwise_fill_array(int ** arr, int N, int index)
{
for(int j=1;j<=10;j++)
{
int* poi=arr[index];//getting pointer to array which i wannna change
int size=0;
while(poi){poi++;size++;}//getting size of pointer array from arr
int* n= new int[size+1];//declaring the new array
for(int i=0; i<size;i++)//copying from all values from old array to new one
n[i]=poi[i];
delete[] poi;
n[size]=j;//adding to the end new value
arr[index]=n;//asigning arr[0] to new diffrent array
}
for(int i=0;i<10;i++)
cout<<arr[0][i]<<" ";
//should print 1 2 3 4 5 6 7 8 9 10
}
int main(){
int N = 10; // how big array should be and how many times it should expand
int** arr = new int*[N];//declaring our array to pointer
for(int i=0;i<N;i++)
{
arr[i]=nullptr;
}
int index =0;//index where I would change the pointer of arr
stepwise_fill_array(arr,N,index);
}
In advance thanks for your help :)
Your style of coding and explaining of problem is tragic , but fortunately I copied with it. When you are trying to get size from while(poi){poi++;size++;} you are getting in trouble. In C\C++ is no possibility to check size of array from pointer to this array. Instead you need increment size in every iteration of function stepwise_fill_array.
Below I give you correct solution(in code are leaks but I doesn't affect in much way on efficiency):
void stepwise_fill_array(int **arr, int N, int index)
{
int size = 0;
for (int j = 1; j <= 10; j++)
{
int *poi = arr[index]; //getting pointer to array which i wannna change
int *n = new int[size + 1]; //declaring the new array
for (int i = 0; i < size; i++)
{
n[i] = poi[i]; //copying from all values from old array to new one
}
n[size] = j; //adding to the end new value
arr[index] = n; //asigning arr[0] to new diffrent array
size++;
}
for (int i = 0; i < 10; i++)
cout << arr[0][i] << " ";
//should print 1 2 3 4 5 6 7 8 9 10
}

how to pass array to constructor in c++?

I am trying to pass an array to constructor in C++ but it is not working:
arrayClass(int *array,int size){
a = new int[15];
for(int i(0); i < size; i++) {
this->a[i] = array[i];
}
this->size = size;
cout << "In second constructor" << endl;
}
in main()
int array[3]={1,2,3};
arrayClass a2(array,3);
Your example is working fine - just take care to delete[] with new[] allocated space accordingly after you're finished (to prevent memory leaking). Also instead of using 15 as hardcoded constant, you probably want to use the parameter size (otherwise for arrays bigger than 15 elements, you would have an memory access violation).
class ArrayClass{
public:
ArrayClass(int* array, int size){
a = new int[size];
for (int i(0); i < size; i++) {
this->a[i] = array[i];
}
this->size = size;
}
virtual ~ArrayClass(){
delete[] a;
}
private:
int* a;
int size;
};
int main(int argc, char** argv){
int array[3] = { 1, 2, 3 };
ArrayClass a2(array, 3);
return 0;
}
Arrays can be allocated in C++ in different ways:
int a[3]; // will allocate the space for 3 elements statically from the stack
int* a = new int[3]; // will allocate space for 3 elements dynamically from the heap
Basically it decides in which memory your array will be located - but there are many differences in these two methods involved - see i.e. What and where are the stack and heap?.
Some main differences are:
stack allocations can't use a dynamical length like a variable i.e. int size = 10; int a[size]; // <- is invalid
stack allocations are 'deleted' automatically when they are out-of-scope
heap allocations have to be deleted[] explicit to not leak memory
The line int* a = new int[3]; will declare a pointer-variable to an memory location where 3 int values can fit in. So after the declaration these 3 values can be addressed directly as a[0], a[1] and a[2]. After all operations are finished delete[] a; is necessary. Because if the pointer a* is getting out-of-scope (i.e. end of your function) the memory for the 3 values is not deallocated automatically.

C++: The value that the pointer is pointing to changes

I am trying to code a class that represents a set of integers. It's a homework assignment but for the life of me I cannot figure out this issue.
In the class "IntSet", I have two private variables; one is a pointer to an array the other is the size of the array. I can create objects of this class and they work as intended. But I have this function named "join" that returns an object of the IntSet class. It essentially concatenates the arrays together then uses that array to create the returning object.
Here is my code:
#include <iostream>
using namespace std;
class IntSet {
int * arrPtr;
int arrSize;
public:
//Default Constructor
IntSet() {
int arr[0];
arrPtr = arr;
arrSize = 0;
}
//Overloaded Constructor
IntSet(int arr[], int size) {
arrPtr = arr;
arrSize = size;
}
//Copy Constructor
IntSet(const IntSet &i) {
arrPtr = i.arrPtr;
arrSize = i.arrSize;
}
/*
* Returns a pointer to the first
* element in the array
*/
int* getArr() {
return arrPtr;
}
int getSize() {
return arrSize;
}
IntSet join(IntSet &setAdd) {
//Make a new array
int temp[arrSize + setAdd.getSize()];
//Add the the values from the current instance's array pointer
//to the beginning of the temp array
for (int i = 0; i < arrSize; i++) {
temp[i] = *(arrPtr + i);
}
//Add the values from the passed in object's array pointer
//to the temp array but after the previously added values
for (int i = 0; i < setAdd.getSize(); i++) {
temp[i + arrSize] = *(setAdd.getArr() + i);
}
//Create a new instance that takes the temp array pointer and the
//size of the temp array
IntSet i(temp, arrSize + setAdd.getSize());
//Showing that the instance before it passes works as expected
cout << "In join function:" << endl;
for (int j = 0; j < i.getSize(); j++) {
cout << *(i.getArr() + j) << endl;
}
//Return the object
return i;
}
};
int main() {
//Make two arrays
int arr1[2] = {2 ,4};
int arr2[3] = {5, 2, 7};
//Make two objects normally
IntSet i(arr1, 2);
IntSet j(arr2, 3);
//This object has an "array" that has arr1 and arr2 concatenated, essentially
//I use the copy constructor here but the issue still occurs if I instead use
//Inset k = i.join(j);
IntSet k(i.join(j));
//Shows the error. It is not the same values as it was before it was returned
cout << "In main function:" << endl;
for (int l = 0; l < k.getSize(); l++) {
cout << *(k.getArr() + l) << endl;
}
return 0;
}
The program compiles and the output as of now is:
In join function:
2
4
5
2
7
In main function:
10
0
-2020743083
32737
-2017308032
I don't know why but the 10 and 0 are always the same every time I recompile and run. Also, if I print out the address of the pointer rather than the value(in both the join function and the main function), I get the same memory address.
Sorry if I misuse terms, I come from a java background, so pointers and such are a little new to me. If any clarification is needed, please ask.
Thanks in advance.
int temp[arrSize + setAdd.getSize()];
This is a local array, its lifetime ends once the function returned.
IntSet i(temp, arrSize + setAdd.getSize());
Here you are constructing an IntSet with this array. In fact the constructor simply changes a member pointer to the value of temp:
IntSet(int arr[], int size) {
arrPtr = arr;
arrSize = size;
}
As a result, since the lifetime of the object that temp and consequently also i.arrPtr is pointing to ends after leaving join, you will have a wild pointer. Dereferencing this pointer later in main invokes undefined behavior.
You need to allocate the array dynamically with new[] and delete it later with delete[]. The same goes for your constructors. Also note that if you use new[] in join and delete[] in the destructor, then you also have to make sure that the copy constructor actually copies the array (create new array with new[] and copy contents). If you simply assign the pointer then both the source and destination object will point to the same array and they will also both try to delete it at deconstruction, again invoking undefined behaviour.
But since this C++, you might as well use a std::vector which does all of this for you. (or std::set if you actually want a integer set)
The quickest fix with your code is to change
int temp[arrSize + setAdd.getSize()];
into this
int * temp = new int[arrSize + setAdd.getSize()];
The thing is that you allocated temp on the stack, so when join() returns that memory is releases. By allocating memory on the heap (as per the fix) the memory is not released when join() returns.
There are other things wrong with your code -- depending on the point of the assignment. I think most of these will be fixed when you consider the implications of having memory on the heap.

Dynamic Arrays passing to functions

I have created 2 dynamic arrays in the main function. I have passed both of them to the function by reference. Then I copy data from smaller dynamic array to the larger dynamic array. I delete the smaller dynamic array. Assign the address of the larger dynamic array to the smaller dynamic array. Now ideally the arr array should have size of 10. However, when I try to print the 6th element of the array in the main, it crashes. Please have a look at the code below:
#include <iostream>
#include <string>
using namespace std;
void func(string * arr, string * brr);
int main()
{
string* arr = new string[5];
arr[0] = "hello0";
arr[1] = "hello1";
arr[2] = "hello2";
arr[3] = "hello3";
arr[4] = "hello4";
string* brr = new string[10];
func(arr, brr);
for(int i = 0; i < 6; i++)
cout << arr[i] << endl;
return 0;
}
void func(string * arr, string * brr)
{
for(int i = 0; i < 5; i++)
brr[i] = arr[i];
for(i = 0; i < 5; i++)
cout << brr[i] << endl;
delete []arr;
arr = brr;
arr[5] = "hello5";
}
This line has absolutely no effect for the caller:
arr = brr;
So after the call, arr points exactly where it used to point before - to a now invalid memory area (because you deleted it).
If this would be a C question, I would advise you to use a pointer to a pointer (string **arr). However, I feel this is nasty in a C++ program. Maybe you want to use a reference somewhere ?
Set this signature for the function
void func(string * & arr, string * & brr)
#cnicutar correctly diagnosed the problem; you'll either need to pass arr by reference (reference to the POINTER, not the array), of have fund return the new value of arr, which the caller can assign.