Passing pointer to a function in C++ - c++

I wrote the following piece of code
#include <iostream>
using namespace std;
void temp (int * x)
{
x=new int [2];
x[0]=1;
x[1]=2;
}
int main()
{
int *ptr;
temp(ptr);
cout<<ptr[0]<<endl;
cout<<ptr[1]<<endl;
return 0;
}
Running it gives seg fault, so is the memory allocation which happens inside temp function local to function? The memory gets deallocated while returning from temp? I know, that to solve this problem, I need to pass pointer to pointer ptr, but still, why exactly does this thing not work?

To alter something in a function in C, you need to pass a pointer to it. In this case, you want to alter a pointer, so you need a pointer to a pointer:
void temp (int** x)
then in the function use *x where you now have x (you will need (*x)[n], as *x[n] means something else)
Then call temp with:
temp(&ptr);
This should solve it in C, and will work in C++.
In C++, you could also pass a reference to a pointer:
void temp(int*&x)
which will allow the syntax you have already to be used unchanged.

Think about this code
void temp(int x)
{
x = 2;
}
int main()
{
int y = 3;
temp(y);
cout << y << '\n';
}
What the output going to be 2 or 3? Of course it's three. Now what's the difference between this and your example? Nothing at all. Unless you use a reference everything in C++ is passed by value. x is a copy of y, so changes to x never affect y. This is true whetever the types involved, its true of ints and its true of pointers.

C++ answer:
You are passing the int* argument into temp by value. This means that you are copying ptr into the function, and the pointer x is a completely separate object. You then assign the result of new int[2] to this copy, but the ptr in main is left unaffected. To be able to modify the pointer passed as an argument, you need to take it by reference:
void temp (int*& x)
{
// ...
}
This means that x now refers to the pointer that is passed as an argument. The alternative solution here is to return an int* instead:
int* temp()
{
int* x = new int [2];
x[0]=1;
x[1]=2;
return x;
}
int main()
{
int *ptr = temp();
// ...
}
However, the caller of temp might be unclear about the ownership of the int object. They need to delete[] it, but this isn't made explicit in the interface. Instead, you can return a std::unique_ptr.

int *ptr;
You created an automatic variable here and you passed it to
temp(ptr);
This is pass by copy so x will get the value of ptr and x scope is within the temp function. It is an automatic variable in that scope.When you return from temp its value is lost.
Now, the memory allocated and pointed to by x is in no way reflected to ptr in main. (They are not connected)
You need to do temp(int*& ptr) i.e. pass by reference. Or temp(int** ptr) i.e. pass by address
Note: You have a memory leak in your temp

You need to pass a ** because you are allocating x inside of your function.

Related

I think this is bad C++ coding ('new' in a function to point to a local variable). Am I correct?

I want to create a class that contains a pointer, and upon initialization, the pointer can be dereferenced to give an integer assigned at initialisation.
This was my first attempt to write this code. This passed compiler and gave me the correct result without warning. However I later think this code has a potential problem.
That is in the constructor, the integer a is created on a stack framed to the constructor function. I am however making 'ptr' pointing to this stack memory address. The problem is this memory can be reused upon maybe calling other functions, so I might get garbage value if I am not lucky.
#include <iostream>
using namespace std;
class P {
public:
int *ptr;
P(int);
};
P::P(int a){
int *ptr = new int (0);
ptr = &a;
}
int main() {
P p(99);
cout <<*(p.ptr) <<endl;
}
A better way would be to create an integer variable on heap, copy the value of a to that variable, and make ptr pointing to that memory space on heap.
P::P(int a){
int *i = new int (0);
*i = a;
ptr = i;
}
Is my analysis correct?
Thanks!
The statements
int *ptr = new int (0);
ptr = &a;
are problematic, but probably not because of the reasons you think.
The reason it's problematic is because you define a new and distinct local variable ptr inside the function. This is not the same as the P::ptr member variable.
There's also a second problem, which is a memory leak. You allocate memory with new, but you never free the memory with delete.
If you really is required to use a raw and non-owning pointer to a single int value, I recommend you do it using a constructor initializer list:
P(int a)
: ptr{ new int(a) }
{
// Empty
}
Here new int(a) will create a new int value and copy the value of a into it.
Remember to then create a destructor which free's the memory you have allocated. And then you need to learn about the rules of three, five and zero.
To use the rule of zero, and to avoid memory leaks and make life simpler, use a smart pointer like std::unique_ptr:
struct P
{
std::unique_ptr<int> ptr;
P(int a)
: ptr{ std::make_unique<int>(a) }
{
}
};
And of course, since it's just about a single int value, and you don't need a reference to the original value, there's no need for pointers at all.

Different passing parameters, different output

If we have the following code, the memory for variable b is not taken, when we call function f. But if the function f would have the prototype void f(int* &a) then the memory would be allocated. How is this possible?
#include <iostream>
using namespace std;
void f(int* a)
{
a = new int[10];
a[0] = 55;
}
int main()
{
int *b;
f(b);
return 0;
}
EDIT:
Well I got the main idea but why is still possible then?
void f(int a[])
{
a[0] = 5;
}
int b[] = {1,2,3,4,5};
f(b);
//The value of b[0] will be 5 after the end of function call
You are passing the pointer by value, so f has its own copy of it. The pointer a is local to f, so the caller has no access to it (and the memory allocated is leaked, BTW).
When you pass the pointer by reference, a is semantically the same pointer as was passed. So the pointer passed by the caller points to the memory allocated in the function.
Pointer int * b; is actually a variable. A variable which hold an memory address of an integer. For example:
int n;
int* b = &n; // pointer b is pointing to n
Since a pointer is a variable you can pass it by value or by reference. Here you pass it by value to the function. Check also the http://en.cppreference.com/w/cpp/language/pointer.
In the case of void f(int* &a) you pass by reference the int* a variable. It is a variable (that hold a memory address of a variable of type int) which it is not initialized to any value yet in your code (in main()).
In your second code. In the function void f(int a[]) when you pass int b[] = {1,2,3,4,5}; with f(b); you make "implicit" conversion of array name to a pointer. The problem is that the function f() does not know the size of the array. For example you use this calls in functions like strlen() where you pass null terminating strings. Check book "The C++ Programming Language", 3rd Edition by Bjarne Stroupstrup page 92.
There is also a basic rule: a[i] <=> (*(a+i)). So your function void f(int a[]) is equal with void f(int* a) definition. Check "Navigating C++ and Object-oriented Design" by Gail Anderson, page 40: http://books.google.gr/books?id=b-NiT6w8FTAC&pg=PA40#v=onepage&q&f=false

How does exactly this code work in C++

For example this code:
#include <iostream>
using namespace std;
void foo(int* x){ cout << "X = " << *x << endl;}
int main()
{
int value = 5;
int *p = &value;
foo(p);
foo(&value);
return 0;
}
In the first call of function foo a copy of pointer p (x) is actually created within the function and deleted as soon as the function ends, right? In the second call of foo the address of variable value is taken and a pointer x is created with that address and is deleted as soon as the function ends, right? Which of these calls is cheaper in terms of stack memory consumption? Or are both the same thing?
They're both similar. The first looks more expensive because you're creating a pointer twice, once as a local variable (inside main) and again as a function parameter (passed to foo), however the "optimization" phase of the compiler will probably turn the first into the second (assuming that the only thing you do with p is pass it, and you don't reuse it later in main).
They are almost identical. The only difference is that you have a pointer object p on the call stack in main, but if you're going to worry about that then you have issues. :)
In the first call, you are passing a variable containing the address of value.
In the second, you are passing the address of value directly.
Note that assignment operator says that both p and &value are the same, so you should be able to pass either one to the function as you have proven.
Pointers have values that can be copied like everything else. They
have value-semantics.
void foo(int* t);
takes a pointer by value. It will create a copy of the pointer
argument and use it inside its body.
int value = 23;
int *p = &value; // &value takes the address of value and use it to copy initialize p
foo(p); // copy the value of the pointer inside foo
foo(&value); // do the same but don't create a temporary

How do I make sure it's safe to return a pointer from a function

Here's my problem:
I read here on StackOverflow that it is unsafe sometimes to return pointers to local variables from a function. For example:
#include<iostream>
using namespace std;
int *foo(void) {
int x[] = {1,2,3};
return x;
}
int main() {
int *numbers;
numbers = foo();
return 0;
}
I'd like to know if this is unsafe, considering that x being a local array, the memory could be unallocated, what's the better way to achieve the same result?
I read here on StackOverflow that it is unsafe sometimes to return pointers to local variables from a function.
It is always unsafe to return pointers to local variables. Indeed it is wrong to do so, and using this pointer will cause undefined behavior. See also this awesome post.
If you want to return data to the calling scope, you could use a std::vector as a copy:
std::vector<int> foo(void){
std::vector<int> x = {1,2,3}; // using C++11 initializer list
return x;
}
If it's a fixed length array (always of size 3), you could use std::array instead.
Depending on your requirements you may also use a static variable. That is, the variable will never go out of scope, s.t. you can return it safely by reference (or by pointer). Note that you have only one copy. If you modify it, it will remain modified. (Make it const & if it's read only.)
std::vector<int>& foo(void) {
// this is only instantiated once when the function is first called
static std::vector<int> x = {1,2,3};
return x;
}
It is unsafe (or rather wrong) to return a pointer to that array, because it does not exist any more when the function returns. The memory could not just be deallocated, but it will be.
Note that it might still accidentially work, but honestly that would be worse than if it didn't work (because it's unpredictable and impossible to debug). Never attempt "but it seems to work" things, even if they seem to work.
This is the same for returning a pointer or a reference, with a const reference being an exception. A const reference keeps the referenced object alive for its own lifetime.
Dynamically allocating or making the object static would be options if you want to return a pointer. Or, just return a temp object by value, relying on the compiler to RVO it out.
It is never safe to to return a pointer to a local variable (it's undefined behaviour in fact). For most implementations those live on the stack, so it can be overwritten when the pointer is used.
You can return an dynamically allocated array:
int* foo() { int* x = new int[3]; ..}
Of course you would need to manually delete the pointer, which makes it hard to write robust, excpetion safe code. Therefore it's typically preferable to use a vector:
std::vector<int> foo() {
std::vector<int> x;
x.push_back(1);
x.push_back(2);
x.push_back(3);
return x;
}
If you use c++11, you can use an initialization list to fill the vector, making the code much nicer:
std::vector<int> foo() { std::vector<int> x = {1,2,3}; return x; }
C++11 has move semantics, which means that in this case returning the vector by value costs almost no performance. For C++03 if performance is essential you could give the function a reference/pointer to vector as a parameter and fill that:
void foo(std::vector<int>& x) {x.clear(); x.push_back(1); ...}
First of all int x = {1,2,3} is syntax error. It should be int x[] = {1,2,3};
This is undefined behaviour. Because the automatic array has a lifetime inside its block where it is defined, that is inside the foo() function. So whenever you return from foo() the storage for x is no more guaranteed to be reserved for you. Therefore if you access that location through pointers then the behaviour is undefined.
To achieve the same result dynamically allocate memory.
int *foo(void){
int x[] = {1,2,3}, *x_to_return;
x_to_return = new int [sizeof (x)/sizeof(x[0])];
memcpy (x_to_return, x, sizeof (x));
return x_to_return;
}
Basically, what you need to do is to dynamically allocate the storage using new, copy your data to the block of memory (base of which is) allocated by new and return that memory address to the caller.
Don't forget to free the allocate the memory once you have finished using it, else your code would have memory leakage.
Also a point to be noted, if you have a declaration like static int x[] = {1,2,3}; then you can return the address of x, because in this case the lifetime of x is the entire program runtime.
As your question is tagged c++ you should use vector, check moooeeeep's answer.
You can either:
Declare x as static
Declare x as a pointer
Yes it is unsafe because the array is allocated on the stack, as such it will be deallocated when the function returns.
Instead of allocating the array inside the function, create it outside and pass a pointer to it to the function. This is just an example:
#include<iostream>
using namespace std;
void foo(int numbers[]){
numbers[0] = 1;
numbers[1] = 2;
numbers[2] = 3;
}
int main(int args, char**argv) {
int numbers[3];
foo(numbers);
cout << numbers[0] << numbers[1] << numbers[2];
return 0;
}
This will print "123".

How to allocate a memory to a given pointer to an array in C++

I've tried to allocate a memory this way:
main:
X** a;
func(a);
func:
func(X** a){
int size = 5;
X* array = (X*)malloc(5*sizeof(X));
//some writing to the array..
a = &array;
}
If using the debugger I see that when I am in the function func everything is okay = i can write to the array and a really points to the array but the moment I am back to the main I something changes and I can't access the array through a (on the debugger it writes something like: Target request failed: Cannot access memory at address 0x909090c3 and so on).
Where is my mistake?
Note: It does compile but has a run-time problem if trying to access (print for example) the array in the main section.
Thanks.
You have to change your main like this:
X* a; // create an uninitialized pointer
func(&a); // pass the address of that pointer to the function
And inside your function, do this:
void func(X** a){
int size = 5;
X* array = (X*)malloc(5*sizeof(X));
//some writing to the array..
*a = array; // change the value of the pointer to point to the array
// you allocated
}
Note that in C++ the way to go would be to use an std::vector<X>:
std::vector<X> func() {
std::vector<X> buffer(5);
// do stuff with buffer
return buffer;
}
std::vector<X> foo = func();
This would create a new vector inside the function and return a copy of that vector to the caller. Note that the copy would be optimized away.
You are changing the local copy of your variable a, it will not propagate to the outside of function (ie. the calling scope). Easiest solution to your problem is to pass a by reference, but you can also pass it using a pointer and dereferencing the pointer inside of your function.
See the below examples.
Using a reference
void func (X*& a) {
X* array = (X*) malloc (5*sizeof(X));
a = array;
}
...
X* a;
func (a);
The ampersand on the line below states that a is being passed by reference, ie. changing it inside the function will make the change propagate to parameter the caller used.
void func (X*& a) {
Using a pointer-to-pointer
This can be hard to comprehend if you are inexperienced when it comes to pointers, but we will make func take a pointer-to-pointer as it's parameter and pass in the address of variable a from main.
Upon dereferencing the pointer-to-pointer we can safely store away the information we want.
void func (X** pointer_to_a) {
X* array = (X*) malloc (5*sizeof(X));
*pointer_to_a = array;
}
...
X * a;
func (&a); // pass in address of a
NOTE
Since you are writing C++ (stated by question title and tag) you should not be using std::malloc, instead refer to operator new.
You're setting the local pointer a to the address of the local pointer array, when you want to set the target of a to the value of array:
*a = array;
and call it as
X * a;
func(&a);
It would be less confusing to return the pointer (i.e. X * func()).
Also, you've tagged this C++ not C, so you shouldn't be using malloc; use the standard containers, or if they don't work for you, allocate using new and manage the memory with a smart pointer.
In main, a is a pointer to a pointer. That means that two things have to exist: the block of memory, and a pointer pointing to it. Then a can point to that pointer. In your attempt, that middle pointer is being allocated on the stack of func, and when func returns, it's destroyed, so that's not going to work.
You could do this:
X* pa;
X** a = &pa;
func(a);
func(X** a){
int size = 5;
X* array = (X*)malloc(5*sizeof(X));
//some writing to the array..
*a = array;
}
Think it over:
a = &array;
array is a local variable allocated on heap, &array will be junk when its scope is over (the function body).