Return with Ampersand - c++

I had to return pointer of a structure object in function but I didn't store them as pointers, so I used return &myStructObject; to return. It does not give any compile-time error but what i'm trying to do is correct?

If structure object you are referring to is local to the function then you should not return the address of that struct object. This is because when your function returns call to its caller then all local variables are destroyed from memory.
For e.g:-
Below is a fatal error
int* myFunc ()
{
int p = 4; // memory is allocated for p.
// do something.
return &p; // memory for p is deallocated and you are returning pointer to that memory
}

If the struct variable whose pointer you want to return is still in scope after returning from the function, what you are doing is correct.
On the other hand, if the struct variable in question is local to the function and will be destroyed (freed) once you return from the function, then the pointer you will return will be a dangling pointer, and will not serve your purpose.
EDIT:
By "will not serve your purpose", I mean it will not do what you think it will! There's no point discussing what harms it can do, when you are sure it doesn't do what you expect it to do!

If you have got something local in a function and you are returning address to that, it will be lost i.e. nullified. The reason is that the function you are returning the address from will be POPped from the stack and anything non-static (non-global) will be lost. In essence, anything that the programme memory hasn't got as a "lifelong" resource will be gone. You can pass pointers as an argument to the function and dereference it to modify value pointed by the pointer. But anything that is non-static (or non-global) and returned as an address will cause you access violation-type errors.

Related

Do pointer return types always needs to be allocated on heap?

I am new to C++ and I am currently learning Heap and Stack. In our class we had a problematic function like this
int* Problematic(int capacity) {
int data[capacity];
// do something
return data;
}
I know this won't return anything but a dangling pointer(is it?) since stack will deallocate everything in the function when it finishes executing. And here comes my questions:
Will this problem happened to all the functions which their return type is a pointer but they are running on stack?(Since they just return an address and stack delete every thing when the function finished running)?
Is there any other things that pointer can do besides connecting stack to heap(Like Pointing to an address on heap)?
From my understanding, the difference between stack and heap is that for stack, instead of manually allocating memory by programmer, stack allocating memory automatically by system continuously. So I am wondering if I have a function like this
int ReturnInt() {const int a = 5;return a;}
what actually this function returns, if it returns an address, won't stack deleted the 5 as before? If this function returns an integer 5, how to explain this integer in memory since it just add 4 bytes in RAM and changes still happens in memory address?
Thank you so much for help :)
Yes. Returning a local non-static address has little value. Such returned addresses are unusable for dereferencing. You can still printf("%p\n",(void*)the_address) them but that's about all you can do with them. (Returning the address of a local static makes sense, though. Such a returned local address is safe to dereference.)
Pointers can point to anything: globals, statics, and they can be passed from a caller (who could allocate their target on the stack for example).
int ReturnInt(){const int a = 5;return a;} returns through a register on most platforms. If that's not possible, the compiler will have made sure the caller has stack-allocated space for the return value.
Will this problem happened to all the functions which their return type is a pointer but they are running on stack?(Since they just return an address and stack delete every thing when the function finished running)?
Yes, if they return a pointer to something allocated on the function's stack.
Is there any other functions that pointer has besides connecting stack to heap(Pointing a address on heap)?
Sure. For example, one object allocated from the heap might contain a pointer to another object allocated on the heap.
From my understanding, the difference between stack and heap is that for stack, instead of manually allocating memory by programmer, stack allocating memory automatically by system continuously. So I am wondering if I have a function like this int ReturnInt() {const int a = 5;return a;} what actually this function returns, if it returns an address, won't stack deleted the 5 as before? If this function returns an integer 5, how to explain this integer in memory since it just add 4 bytes in RAM and changes still happens in memory address?
It doesn't return an address. Its return type is int and it returns the integer value 5, not any address at all. The function returns the value 5. There is no requirement that the implementation store that 5 in memory and it may or may not do so as it wishes. It could, for example, return the value 5 in a register.
#2 Question (not clear but heres a shot)
you also have a third storage space option - static. Thats fixed size determined by what you ask for at compile time
#include<stdio.h>
char buffer[500];
...
int main(int argc, char**argv){
}
buffer is 500 bytes statically allocated
absolutely. If a function returns a pointer to a data allocated on its stack, the stack becomes invalid after exit from the function and the pointer will point to invalid location.
the question is not clear.
stack is a space in memory which is allocated for internal use of a function. It gets reserved for the function call and is released for any other use after function returns. In your example int ReturnInt() {const int a = 5;return a;} there is no pointers. The result is returned by value. In other words, the value of variable a is copied to the location of the function return value before its return. This preserves the value and allows it to be used after the function return. The following with pointers will not work: int *ReturnIntPtr(){int a = 5; return &a;}. Here you return a pointer to stack which is not valid after the return.

What's the point of passing address of pointer to function that needs pointer to pointer?

I'm reading an example of ffmpeg decoding and it has the address of a pointer being passed to a function:
static AVBufferRef *hw_device_ctx = NULL;
if ((err = av_hwdevice_ctx_create(&hw_device_ctx, type,
NULL, NULL, 0)) < 0) {
What's the point of passing the address of a pointer as an argument?
I understand that when we pass the pointer itself, if the pointer has address 0x123456, then the function is going to be able to modify what's the object that is in this address. But when I pass the address of a pointer, I'm passing the address of where this pointer number is allocated?
If I understood right, I'm passing the address of the variable that stores 0x123456? Why the function needs it?
Also, suppose that I want to store hw_device_ctx in a unique_ptr like this:
std::unique_ptr<AVBufferRed> hw_pointer;
How can I pass it to av_hwdevice_ctx_create? Because I get an error when I do
av_hwdevice_ctx_create(&hw_pointer.get(),...
It says:
expression must be an lvalue or a function designator
When you pass a pointer, you pass pointer by value. So you can modify the variable your pointer points to but not the pointer itself.
If you needed to modify the pointer itself (e.g. point to somewhere else) you pass it by reference or pointer to pointer.
The reason the reference of unique_ptr doesn't work is because you are trying to get a reference of a temporary which will imediately die. If the function accept a const ref it would work but evidently it is not what you are trying to achieve.
You should NOT modify a pointer which is managed by a smart pointer. You can pass the pointer to the smart pointer after function call.
It needs that for the same reason that a function that wants to modify an int needs to be passed a pointer (or reference) to a modifiable int.
That is, your situation is the same as
int f() { return 0; }
void foo(int* x) { *x = 1; }
...
foo(&f());
If you want to manage lifetime with a unique_ptr, let the function create the object first and then hand over ownership of it to the unique_ptr:
AVBufferRef *hw_device_ctx = NULL;
if ((err = av_hwdevice_ctx_create(&hw_device_ctx, type,
NULL, NULL, 0)) < 0) {
..
}
else
{
std::unique_ptr<AVBufferRed> hw_pointer(hw_device_ctx);
...
}
As you wrote, when you pass the pointer to something, the function can modify the data in the object/memory that the pointer points to. But you, i.e. your application, has to allocate the memory itself.
When you pass the address of a pointer, the function that is called can allocate the memory itself and return the newly allocated object or memory through the pointer.
Btw.: Read the documentation if your application has to free the memory again!
If I understood right, I'm passing the address of the variable that stores 0x123456?
Yes, you understood it right. You are passing the address of a variable that holds another address.
Why the function needs it?
In most cases a function declares a pointer to pointer as a parameter when the argument when passed to this function is normally a pointer by design and the function needs to modify the argument itself (in your example, the variable that holds 0x123456).
How can I pass it to av_hwdevice_ctx_create? Because I get an error when I do
You shouldn't. This functions lets the caller the responsibility to free the memory after usage, however if you really want to do this, you can assign a variable with unique_ptr.get() and then pass the address of this new variable (which will break the whole idea of the smart pointer you are using - in this particular case you should use a raw pointer).

Base and derived class allocation

In the code below, drvdCls derives from bseCls. This code compiles and runs as it is. I however find an issue here: newBse will get deallocated after Test() exits. Am I right?
bseCls* Test()
{
bseCls* newBse = new drvdCls();
drvdCls newDrvd;
newBse = &newDrvd;
return newBse;
}
The object originally pointed to by newBse will be leaked. When you assigned the address of newDrvd to newBse you are losing the pointer to the heap-allocated object, and you will not be able to delete it. This memory will be unusable until the process terminates.
Additionally, you are returning the address of a stack-allocated object as a pointer, which is bad for two reasons:
The object's destructor will have been called before the function returns, meaning you would be using a pointer to a destructed object.
The memory allocated for the object lives on the stack and will almost certainly be clobbered by future function calls. At that point, your pointer will be point at something that is not a bseCls, but you will be using it as though it were.
If you use the pointer returned by this function, you are invoking undefined behavior and your program has license to do anything.
No, it won't be automatically deallocated. Every call to new must be matched by a call to delete. But that's not the only problem with your code, you're also returning the address of a local variable from the function.
newBse = &newDrvd; // memory leak, pointer to previously allocated object is lost
return newBse; // newDrvd is destroyed when function exits, so returned
// pointer points to invalid memory
What you probably want to do is
bseCls* Test()
{
return new drvdCls();
}
Now the caller must call delete on the returned pointer after using it. What you should do is
std::unique_ptr<bseCls> Test()
{
return new drvdCls();
}
Now the allocated object will automatically be deleted when the returned unique_ptr goes out of scope.

Pointer - returning Local reference in C++

I'm not sure if this question has been asked before ( searched through SOF and couldn't find an answer)
I wrote a LinkedList class and a function to reverse it.The function as follows,
struct LinkedList::element* LinkedList::recurrsiveReverseList(element* head){
element* tempList;
if(head->next == NULL){
return head;
}else{
tempList = recurrsiveReverseList(head->next);
head->next->next = head;
head->next = NULL;
return tempList;
}
}
here I am declaring a local pointer variable and making some changes to it and returning it back to the caller. In C++, when I declare a local variable inside a function the scope exists only inside the function. Now when I return the pointer from the function how does it work? I am able to understand the logic and get the result (luckily) but I am not able to completely understand the working here.
Can somebody clear my doubt?
The scope of tempList terminates when you exit the function but tempList is a pointer to a block of memory whose scope does not terminate there because it's been undoubtedly allocated by new. Memory allocated in such a way is valid right up until the point you delete it, regardless of how many functions you go in to or out of.
By passing the pointer back to the caller, it preserves said pointer elsewhere, where you can use it.
A simple example:
static char *fn (void) {
char *rv = new char[42];
return rv;
}
int main (void) {
char *x = fn();
delete [] x;
return 0;
}
In the code above, the scope of rv is limited to the fn function after it's declared.
The scope of x is limited to the main function after it's declared.
However the memory allocated by new comes into existence within fn and continues to exist after returning to main. The address of said memory, initially stored in rv, is transferred to x by the assignment of the fn return value to x.
Not sure if someone else explained it this way, but the pointer itself is nothing more than a number, like... 0x12345678. That number in turn addresses a position in the memory of a computer that contains the actual value you are looking for, which is the linked list node.
So when you return that address, it's okay that the original variable was destroyed. Like copying down a street address to a different piece of paper, then throwing away the original paper. The house that is at the address you have is still there.
The pointer object tempList ceases to exist when you leave the function. But that's ok; you're returning (a copy of) the value that was stored in the object, not the object itself. It's just like
int n = 42;
return n;
(Returning the address of a local variable is what gets you into trouble.)
I assume your linked list nodes are allocated on the free store (i.e. with new).
When you create an object with new, it is created on the free store and exists until you call delete on it. You can make as many pointers to that location as you want, and it exists independent of any function calls it may have been made in. So in this function, you are just returning a pointer by value to that location on the free store. The pointer is just a number which is the address of the object, like returning an int by value.
tl;dr: You obviously know you can return local objects by value because a copy is made. In this function, it returns a copy of the pointer which points to a location on the free store which is only destroyed when delete is called with a pointer to that memory location.
As another note, you probably should not return a pointer to the new head of the list but rather take a pointer to the head of the list by reference and change the list through that, so if someone forgets to assign their old head pointer to the one returned by recurrsiveReverseList, things aren't messed up.
The scope of usage of tempList variable is limited within the method as its local, but it holds a memory address which is what is returned.
The code that call its will receive this memory address, not the variable tempList.

Scope and return values in C++

I am starting again with c++ and was thinking about the scope of variables.
If I have a variable inside a function and then I return that variable will the variable not be "dead" when it's returned because the scope it was in has ended?
I have tried this with a function returning a string and it did work.
Can anyone explain this? Or at least point me to some place that can explain this to me please.
Thanks
When the function terminates, the
following steps happen:
The function’s return value is
copied into the placeholder that was
put on the stack for this purpose.
Everything after the stack frame
pointer is popped off. This destroys
all local variables and arguments.
The return value is popped off the
stack and is assigned as the value
of the function. If the value of the
function isn’t assigned to anything,
no assignment takes place, and the
value is lost.
The address of the next instruction
to execute is popped off the stack,
and the CPU resumes execution at
that instruction.
The stack and the heap
When you return a value, a copy is made. The scope of the local variable ends, but a copy is made, and returned to the calling function. Example:
int funcB() {
int j = 12;
return j;
}
void A() {
int i;
i = funcB();
}
The value of j (12) is copied and returned to i so that i will receive the value of 12.
It really depends on what kind of variable you are returning. If you return a primitive then it is returned by copy, not by reference so the value is copied to the top of the stack (or, more often placed into a register) where the calling function can get it. If you allocate an object or memory on the heap and return a pointer then it doesn't die because it's on the heap, not the stack. If you allocate something on the stack, however, and return it, that would be a bad thing. For instance, either of these would be very bad:
int *myBadAddingFunction(int a, int b)
{
int result;
result = a + b;
return &result; // this is very bad and the result is undefined
}
char *myOtherBadFunction()
{
char myString[256];
strcpy(myString, "This is my string!");
return myString; // also allocated on the stack, also bad
}
Just for a little bit more of a memory-model oriented explanation: when a function is called, a temporary space is made for the function to put its local variables, called a frame. When the function (callee) returns its value, it puts the return value in the frame of the function that called it (caller), and then the callee frame is destroyed.
The "frame is destroyed" part is why you can't return pointers or references to local variables from functions. A pointer is effectively a memory location, so returning the memory location of a local variable (by definition: a variable within the frame) becomes incorrect once the frame is destroyed. Since the callee frame is destroyed as soon as it returns its value, any pointer or reference to a local variable is immediately incorrect.
This depends on the type of the returned item. If you are returning by value, a new copy of the variable is made to return to the caller. I thins case you do not need to worry about object lifetime, but you may need to worry about the costs of copying objects (but please don't prematurely optimze - correctness is much more important):
std::string someFunc( std::string& const s)
{
return s + "copy";
}
If the function is returning a reference, then you need to be careful about what you're returning because it's lifetime needs to extend beyond the function's lifetime and the caller will not necessarily be able todelete it if you're using new to create the object:
std::string& someFunc2( std::string const& s)
{
return s + "reference to a copy"; // this is bad - the temp object created will
// be destroyed after the expression the
// function call is in finishes.
// Some, but not all, compilers will warn
// about this.
}
Of course, returning pointers will have similar lifetime considerations.
The local variable is copied to the return value. Copy constructors are called for non-trivial classes.
If you return a pointer or reference to a local variable you will have trouble---just as your intuition suggested.