Is this code is completely valid? Will returning a pointer here will not throw us to undefined behavior?
#include <iostream>
using namespace std;
int* lab(int* i) {
int k=9;
i=&k;
return i;
}
int main(void) {
int* i=0;
cout << *lab(i) << endl;
return 0;
}
EDIT: how valid code can look like?
No sir. That is not valid. You can't return a pointer to a local variable. Once lab() exits k does not exist and dereferencing a pointer to it causes undefined behavior.
Think about where k is stored. Automatic variables that you take the address of are stored on the stack. The stack grows when functions are entered and shrinks when they exit. When lab() returns the stack space that was allocated to k is reclaimed and can be reused by the runtime, possibly for other local variables in some other functions.
There are a couple of ways to fix this. The easiest is to have the caller provide a location to store the value in rather than having lab() try to find space. This eliminates the problem of k being deallocated when lab() returns.
int* lab(int* i) {
*i = 9;
return i;
}
int main(void) {
int k;
cout << *lab(&k) << endl;
return 0;
}
Another way is to declare k as static. Static variables are stored in permanent storage somewhere, not on the stack, so their addresses remain valid throughout the lifetime of the program.
int* lab() {
static int k=9;
return &k;
}
And yet another way is to allocate memory on the heap using new.
int* lab() {
int* i = new int;
*i = 9;
return i;
}
int main(void) {
int* i = lab();
cout << *i << endl;
delete i;
return 0;
}
int k will be deleted when the function returns. Hence i will point to an unallocated part of memory. ERROR
No it is not valid. lab returns a pointer to a variable local variable. That pointer is not valid once lab exists. Access it is undefined behavior.
Related
I have passed pointer to a pointer as a parameter to function and the goal is to make an array inside of that function. I have done that step properly and also inside of the function checked the *address and value of the array(local) as well as pointed by the pointer(op_ptr_array_) and they are the same(as desired).
But the problem is occurring while I want to dereference the provided pointer(op_ptr_array). The values are wrong while addresses are matched with the pointed array(local).
My idea is that as the address of op_ptr_array(pointer passed to the function) is equal to the local and op_ptr_array_ (array and pointer inside of the function) so using a for loop *(op_ptr_array+i) will provide me the result where i < op_size.
The approach I have taken is as follows:
#include <iostream>
void op_calculation(unsigned int* ip_ptr_array_,
unsigned int ip_size_,
unsigned int** op_ptr_array_,
unsigned int* op_size_)
{
*(op_size_) = ip_size_ + 2;
std::cout<<"op_size_ address: "<<op_size_<<std::endl;
std::cout<<"op_size_ value: "<<*(op_size_)<<std::endl;
unsigned int local[*(op_size_)];
std::cout<<"making local array to be pointed by op_ptr_array_\n";
for (unsigned int i = 0; i< *(op_size_); i++)
{
local[i]=i+1*3;
std::cout<<local[i]<<" ";
}
std::cout<<"\n";
*op_ptr_array_ = &local[0];
local[3] = 87; // for checking pointer charecter
for (unsigned int i = 0; i < *(op_size_); i++)
std::cout<<"array address: "<<&local[i]<<" ,op_ptr_array address: "<<(*op_ptr_array_)+i<<" ,val of array: "<<local[i]<<" ,val at op_ptr_array: "<<*((*op_ptr_array_)+i)<<std::endl;
// here value and addresses are same which is desired
}
int main()
{
unsigned int ip_size = 10;
unsigned int* ip_ptr_array = new unsigned int[ip_size];
unsigned int op_size;
unsigned int* op_ptr_array;
for(unsigned int i = 0; i < ip_size; i++)
{
ip_ptr_array[i] = i+2*2;
}
op_calculation(ip_ptr_array,
ip_size,
&op_ptr_array,
&op_size);
std::cout<<"Value printing after operation of op_calculation function\n";
std::cout<<"op_size: "<<op_size<<std::endl;
std::cout<<"op_ptr_array\n";
for(unsigned int i = 0; i < op_size; i++)
std::cout<<"Address: "<<(op_ptr_array+i)<<" , Value: "<<*(op_ptr_array+i)<<"\n";
/* Here only addresses are same with `local array` and
address pointed by op_ptr_array_ pointer` which you will find in op_calculation
function but values are different*/
std::cout<<"\n";
return 0;
}
Any idea where I am making the mess is highly appreciable.
Variable local is being declared as a local variable (i.e. on the stack). This falls out of scope when the function op_calculation exits, which means that the memory originally used to allocate local may be used for something else.
This can be corrected by converting local to a pointer and using new to allocate memory for the array’s contents or by declaring local as static, which will place the contents elsewhere in RAM. Keep in mind, if you use static any future calls to op_calculation will overwrite the contents of the array, even if it is still in use elsewhere. This would not be a problem if you used new, but if you use new you will need to remember to deallocate the array using delete[] when it is no longer needed.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 7 years ago.
#include<iostream>
using namespace std;
int *Arr(int y,int size){
int arg[size];
for(int i=size-1;i>=0;i--){
arg[i]=y%10;
y=y/10;
}
return arg;
}
int main(){
int *p=Arr(2587,4);
for(int j=0;j<4;j++){
cout<<p[j]<<" ";
}
return 0;
}
> Blockquote
I dont why this isn't working ...I'm trying to back an array but the problem is in the second digits.Can somebody help ;) thanks
The problem is you are putting your result into a local array that is destroyed when the function ends. You need to dynamicaly allocate the array so that its life-span is not limited to the function it was created in:
#include<iostream>
using namespace std;
int *Arr(int y, int size)
{
// This local array will be destroyed when the function ends
// int arg[size];
// Do this instead: allocate non-local memory
int* arg = new int[size];
for(int i = size - 1; i >= 0; i--)
{
arg[i] = y % 10;
y = y / 10;
}
return arg;
}
int main()
{
int *p = Arr(2587, 4);
for(int j = 0; j < 4; j++)
{
cout << p[j] << " ";
}
// You need to manually free the non-local memory
delete[] p; // free memory
return 0;
}
NOTE:
Allocating dynamic memory using new is to be avoided if possible. You may want to study up on smart pointers for managing it.
Also, in real C++ code, you would use a container like std::vector<int> rather than a builtin array
Of course it is not working.
At best, the behaviour is undefined, since Arg() is returning the address of a local variable (arg) that no longer exists for main(). main() uses that returned address when it is not the address of anything that exists as far as your program is concerned.
There is also the incidental problem that int arg[size], where size is not fixed at compile time, is not valid C++. Depending on how exacting your compiler is (some C++ compilers reject constructs that are not valid C++, but others accept extensions like this) your code will not even compile successfully.
To fix the problem, have your function return a std::vector<int> (vector is templated container defined in the standard header <vector>). Then all your function needs to do is add the values to a local vector, which CAN be returned safely by value to the caller.
If you do it right, you won't even need to use a pointer anywhere in your code.
I'm going to write a piece of code (Function) that returns a pointer to an array.
but I don't know how to do that.
The code I wrote is :
int* prime_factor(int temp){
int ctr;
int *ret;
int i = 0;
while (temp != 1){
ctr = 2;
if (temp%ctr != 0){
ctr++;
}
else {
*(ret + i) = ctr;
temp /= ctr;
}
}
return ret;
}
I guess that there's a need to such the thing :
else {
ret = new int[1];
*(ret +i) = ctr;
temp /= ctr;
}
But as you know , implementation of this stuff needs to be deleted the memory that you have allocated , so we have to delete the memory outside of the function , so it going to be nonstandard function.
Indeed, i want to calculate the Prime factors of a number then return them out.
Any idea to do that ? I don't know what should I do to gain the goal.
thank you so much.
I see your question has also the tag C++ so, you could use C++. I don't really know what you mean with without static integer ....
Use vector.
#include <vector>
vector<int> prime_factor(int number)
{
int ctr = 2;
vector<int> factors;
while (number != 1)
{
if (number % ctr != 0)
ctr++;
else
{
factors.push_back(ctr);
number /= ctr;
}
}
return factors;
}
As you will be using the vector with integers it knows how to destroy ("delete") it self.
Example:
int main()
{
for (auto &x : prime_factor(20)) // C++11
{
cout << x << endl;
}
}
Output:
2
2
5
Yes, putting burden of deleting the array on user is not preferable. Here you would be better off using vector instead of plain array.
You can also pass array as an argument(created in the caller so that it would be more intuitive to use delete on that array) to this function.
The line *(ret + i) = ctr; will create a memory violation right away, since your ret pointer has no allocated memory pointing to. You nee do preallocate a memory for it, either statically (array declaration) in the code CALLING this function, and passing it to the function as a parameter, or dynamically (using malloc or similar) and then freeing it in some point. Dynamic allocation can be done either in the function itself or in the calling code. But again, free the memory afterwards.
int *ret;
In your case ret doesn't point to any memory location.You are trying to reference some unallocated memory location which might cause segmentation fault.
Just to show how to return a pointer and free it below is the example:
int *some()
{
int *ret = malloc(sizeof(int));
*ret = 10;
return ret;
}
int main()
{
int *p = some();
printf("%d\n",*p);
free(p);
}
"But as you know , implementation of this stuff needs to be deleted the memory that you have allocated , so we have to delete the memory outside of the function , so it going to be nonstandard function."
To avoid that dilemma c++ has introduced Dynamic memory management support.
Instead of using raw pointers like int* use one appropriate of
std::unique_ptr<int> (to transfer ownership)
std::shared_ptr<int> (to share ownership)
std::weak_ptr<int> (to share ownership, but not count as reference)
std::auto_ptr<int> (to transfer ownership "the old way")
Besides that, it looks like using a std::vector<int> would be much more appropriate, than using a simple int*. The std::vector<int> class also is purposed to release you from getting the dynamic memory management right on your own.
This question already has answers here:
Can a local variable's memory be accessed outside its scope?
(20 answers)
Closed 9 years ago.
This code takes value returned from a function, creates and puts it in a new address space called variable 'b'
int main()
{
int b;
b = topkek();
std::cout << &b;
};
int topkek()
{
int kek = 2;
return kek;
};
Now I understand because variable kek was inside of topkek method I can not access it from main() method. With C++ and pointers, I figured out how I could access a variable declared inside a method even after the method has terminated, look at this code.
int main()
{
int * a;
a = topkek(); //a is now pointing at kek
std::cout << *a; //outputs 2, the value of kek.
*a = 3;
std::cout << *a; //output 3, changed the value of kek.
std::cin >> *a;
};
int * topkek()
{
int kek = 2;
int* b = &kek; //intializing pointer b to point to kek's address in stack
return b; //returning pointer to kek
};
Is this method safe? Would the compiler prevent kek's address space being overwritten later in code because it still understand it's being used?
This is undefined behavior: once the function finishes, accessing a variable inside it by pointer or reference makes the program invalid, and may cause a crash.
It is perfectly valid, however, to access a variable when you go "back" on the stack:
void assign(int* ptr) {
*ptr = 1234;
}
int main() {
int kek = 5;
cout << kek << endl;
assign(&kek);
cout << kek << endl;
}
Note how assign has accessed the value of a local variable declared inside another function. This is legal, because main has not finished at the time the access has happened.
No it is not safe. After your function finished execution, you are not pointing to an int anymore but just to some random place in memory. Its value could be anything since it can be modified elsewhere in your program.
Most definitely not safe. Undefined behavior will result.
When a local variable is "created", the compiler does so by giving the variable some space on the the stack [1]. This space is available for the variable as long as you are inside that function. When the function returns, the space is released, and available for other functions to use. So the address of b in your second code is returning a pointer to memory that will be releasted just after the return finishes.
Try adding something like this:
int foo()
{
int x = 42;
cout << "x = " << x << endl;
return x;
}
and call foo after your call to topkek, and it's pretty certain that the value in kek (or pointed to by kek) will change.
[1] For the pedants: Yes, the C++ standard doesn't specify that there needs to be a stack, or how local variables are supposed to be used, etc, etc. But in general, in nearly all compilers available today, this is how it works.
This will be safe:
int * topkek()
{
static int kek = 2;
int* b = &kek; //intializing pointer b to point to kek's address in stack
return b; //returning pointer to kek
};
Locally allocated automatic types will be automatically deallocated when exiting the function scope. The pointer you return will then point to deallocated memory. Accessing this memory will result in undefined behaviour.
int* topkek() {
int kek = 2; // Create a local int kek
int* b = &kek; // Declare pointer to kek
return b; // Return pointer to local variable. <-- Never do this!
}; // kek is destroyed and the returned pointer points to deallocated memory.
This is undefined behavior. After returning from the function, kek does not exist any more, and the pointer returned points into nirvana, to the location where kek once was. Accessing it gives undefined behavior. Undefined behavior means, anything can happen. You could indeed get the value that once was in kek or your application crashes, or you get some garbage value, or your compiler sees fit to order you a pizza online, with extra cheese, please.
This is undefined behavior, kek is a local variable and the memory it resides in will be released once you exit topkek. It may seem like it works but since it is undefined anything can result, it can break at any time and you can not rely on the results.
First, this is definitely unsafe as others have noted. But based on your usage, I think you might actually be trying to define an object. For example, this code might be what you want:
struct topkek{
int kek;
int *operator()() {
kek = 2;
return &kek;
}
};
int main()
{
topkek mykek;
int *a = mykek(); // sets mykek.kek to 2, returns pointer to kek
std::cout << *a;
*a = 3;
std::cout << *a;
std::cin >> *a;
};
This will give you clean access to the underlying kek variable in a totally safe way. You can of course put any code you want into the operator() method.
I have the following sample code. Just wanted to know if is valid to take address of a local variable in a global pointer and then modify it's contents in a sub function. Following program correctly modifies value of variable a . Can such practice cause any issues ?
#include <iostream>
#include <vector>
using namespace std;
vector<int*> va;
void func()
{
int b ;
b = 10;
int * c = va[0];
cout << "VALUE OF C=" << *c << endl;
*c = 20;
cout << "VALUE OF C=" << *c << endl;
}
int main()
{
int a;
a = 1;
va.push_back(&a);
func();
cout << "VALUE IS= " << a << endl;
return 0;
}
This is OK, as long as you don't try to dereference va[0] after a has gone out of scope. You don't, so technically this code is fine.
That said, this whole approach may not be such a good idea because it makes code very hard to maintain.
I'd say that if your program grows you could forget about a change you made in some function and get some weird errors you didn't expect.
Your code is perfectly valid as long as you call func() while being in the scope of a. However, this is not considered to be a good practice. Consider
struct HugeStruct {
int a;
};
std::vector<HugeStruct*> va;
void print_va()
{
for (size_t i = 0; i < va.size(); i++)
std::cout<<va[i].a<<' ';
std::cout<<std:endl;
}
int main()
{
for (int i = 0; i < 4; i++) {
HugeStruct hs = {i};
va.push_back(&hs);
}
print_va(); // oups ...
}
There are 2 problems in the code above.
Don't use global variables unless absolutely necessary. Global variables violate encapsulation and may cause overlay of variable names. In most cases it's much easier to pass them to functions when needed.
The vector of pointers in this code looks awful. As you can see, I forgot that pointers became invalid as soon as I left for-loop, and print_va just printed out garbage. The simple solution could be to store objects in a vector instead of pointers. But what if I don't want HugeStruct objects to be copied again and again? It can take quite a lot of time. (Suppose that instead of one int we have a vector of million integers.) One of the solutions is to allocate HugeStructs dynamically and use vector of smart pointers: std::vector<std::shared_ptr<HugeStruct>>. This way you don't have to bother about memory management and scope. Objects will be destroyed as soon as nobody will refer to them.