returning reference to a pointer - c++

I was looking at this link about returning reference to a pointer. According to this, we have to return reference to a static or global variable. My question here is, in case we create memory block inside a function using new, why application will crash since memory allocated using new is permanent until deleted? I wrote below code to test this and it crashes and if I make ptr static inside the function, there is no issue.
int* &returnPtrByRef(int numElements)
{
int *ptr = new int(numElements);
return ptr;
}
int main (void)
{
int num=5;
int *&ptrRef = returnPtrByRef(num);
for(int cnt = 0; cnt < num; cnt++)
*(ptrRef + cnt) = cnt * 2;
for(int cnt = 0; cnt < num; cnt++)
cout << *(ptrRef + cnt) << '\t';
return 0;
}

It's useful to think of references as syntactic sugar for pointers. So let's rewrite your function using a double pointer, instead of a reference to a pointer:
int** returnPtrByRef(int numElements) {
int *ptr = new int(numElements);
return &ptr;
}
Here, we can see that we're actually referring the pointer to the piece of stack allocated memory that points to the memory we allocated on the heap. Once the function returns, this stack allocated memory (8 bytes to hold the pointer), no longer exists.

Related

SIGSEGV error while declaring array without creating new int[size]

I tried to write code where i have to return the pointer pointing to the first element of array.
I tried using this:-
int *construct(int arr[],int n)
{
int size=(int)(ceil(log2(n)));
size=2*pow(2,size)-1;
int st[size];
for(int i=0;i<size;i++)
st[i]=INT_MAX;
constructUtil(arr,st,0,n-1,0);
int *pt=&st[0];
return pt;
}
This gave me error.
But when i declared the same array like this:
int *st=new int[size];
It executed successfully.
What is the difference between these two?
You canĀ“t return a pointer to a local array in C. You have to use malloc to allocate the memory and generate a pointer to a memory region for your array. Now you can return the pointer and the memory stays valid:
#include <stdio.h>
#include <stdlib.h>
int* construct(int n);
int main()
{
int* ArrayPointer = construct(100);
printf("Address: %p", ArrayPointer);
for(int i = 0; i < 100; i++)
{
printf("%i\n\r", ArrayPointer[i]);
}
free(ArrayPointer);
return 0;
}
int* construct(int n)
{
int* array = (int*)malloc(n * sizeof(int));
for(int i = 0; i < n; i++)
{
array[i] = i;
}
return array;
}
The instruction new does something similar to the malloc function (not exactly the same). The key operation of new is to ask the OS for some free memory for dynamic allocation (like malloc but from another memory pool). See the difference between malloc and new here. Another option (without dynamic memory) is to declare a static array with a fixed size. So the compiler will reserve the memory and you can pass the address of this array to your function

Why do we really need pointers in Programming specifically C++

I can't really understand the difference between Dynamic and static allocation,they say Dynamic allocation happens while executing the program and static only while compiling and we can't allocate manually while execution but,
#include <iostream>
using namespace std;
int main()
{
int size , a = 0;
cout << "Enter the size of Array: ";
cin >> size;
int A[size][size];
for(int i = 0 ; i < size ; i++)
{
for(int j = 0 ; j < size ; j++)
cout << a++ << '\t';
cout << endl;
}
system("pause");
return 0;
}
This program will allocate the Array size while execution.
The real point of dynamic allocation is that you control the lifetime of the objects being allocated. Dynamically allocated objects exist until you deallocate them. It's not really anything to do with arrays, although that is often the context in which beginners are first taught about allocation.
Consider these two functions
int* bad()
{
int x = 123;
return &x;
}
int* good()
{
int* x = new int(123);
return x;
}
Both functions create an int and return a pointer to that int.
The bad function is incorrect because the x variable is destroyed when the function exits, so it returns a pointer to an object which has been destroyed.
The good function creates an int dynamically, that object will never be destroyed (unless the program deletes it). So this function is correct.
Incidentally int size; ... int A[size][size]; is not legal C++. Some compilers allow it, but other compilers would not.

How can I reallocate array which allocated in another function?

I'm new to C programming.
I want to make a linked list, so I did, but it doesn't work.
After I do that, I made it for a test, but still it gives an error.
malloc: error for object 0xa000000000000000: pointer being realloc'd was not allocated
set a breakpoint in malloc_error_break to debug
How can I reallocate this array?
void Allocate(int **arr,int totalNum, int subNum)
{
for(int n=0;n<(totalNum+1);n++)
{
arr[n] = (int*)realloc(arr[n],(size_t)((subNum+1)*sizeof(int)));
}
}
int main()
{
int totalNum = 20;
int subNum = 5;
int **arr;
arr = (int**)malloc((totalNum+1)*sizeof(int*));
Allocate(arr,totalNum, subNum);
for(int n=1;n<(totalNum+1);n++)
{
for(int s=1;s<(subNum+1);s++)
{
arr[n][s] = rand()%5;
cout<<"arr["<<n<<"]["<<s<<"]: "<<arr[n][s]<<endl;
}
}
}
The program crashes because arr[n] is uninitialized when realloc() is invoked.
i do not fully understand why you want to realloc() instead of malloc() in the Allocate() function. but anyway, let's assume realloc() is what you need.
the easiest fix is to initialize arr content.
arr = (int**)calloc((totalNum+1),sizeof(int*));
The first argument to realloc() has to be either NULL or a pointer that was returned earlier by malloc() or realloc(). You passed an array full of uninitialized data to Allocate(), so you're passing uninitialized pointers to realloc() there. You need to initialize them all to NULL first.
arr = malloc((totalNum+1)*sizeof(int*));
for (int i = 0; i < totalNum+1; i++) {
arr[i] = NULL;
}
Allocate(arr,totalNum, subNum);

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.

Initialized in a function and is not initialized in main

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