int* areaofsquare(int len,int width){
int value = len*width;
return &value;
}
int main() {
printf("area=%i\n",*areaofsquare(1,2));
return 0;
}
Why I get memory error from this code? As per my understanding I did not get any error in this code block so why does it not run properly?
Help me out.
Thank you.
You can't just return pointer to stack variable, as it's getting invalidated as the function returns. You can use dynamic memory allocation instead:
int* area(int leangth,int width){
int * area = malloc(sizeof(int));
*area = leangth*width;
return area;
}
int main() {
printf("area=%i\n",*area(5,6));
}
Please note that you create memory leak and it would be better to handle it some way, but in this tiny example it doesn't matter.
You are returning the address of a local function variable in your function area. When the function returns, its stack space is no longer valid, so attempting to access an address to a local variable from that function is undefined behavior.
I don't see why you need to make area return a pointer to an int. Just return area's value and have area's return type just be int instead.
If for some reason you are required to return a pointer to an int (i.e. assignment or deliverable specifications), you have some options:
Use heap memory. Allocate area with malloc, and free it in main after you've printed its value.
Use static to put area into the process' data section rather than in stack memory, so that it persists beyond its scope and an address-of operation on it will continue to work after the function returns.
Related
I have the following C++ code, and I'm running g++ (Ubuntu 7.4.0-1ubuntu1~18.04.1) 7.4.0:
#include <iostream>
const int& getConst() {
int x = 10;
printf("x ptr: %p\n", &x);
const int &y = 10;
printf("y ptr: %p\n", &y);
return y;
}
int main() {
int start = 0;
printf("start ptr: %p\n", &start);
const int &t = getConst();
printf("t: %d\n", t);
printf("t ptr: %p\n", &t);
int end = 0;
printf("end ptr: %p\n", &end);
return 0;
}
And the output of this code is as follows:
root#78600f6683dd:/home/test/question# ./a.out
start ptr: 0x7ffdcd2381f8
x ptr: 0x7ffdcd2381c8
y ptr: 0x7ffdcd2381cc
t: 10
t ptr: 0x7ffdcd2381cc
end ptr: 0x7ffdcd2381fc
There are two things I'm confused about the result:
The memory location of start and end within the function main() are 0x7ffdcd2381f8 and 0x7ffdcd2381fc respectively. The memory locations of variables of main function are ascending. The main function calls getConst() function, but the location of variables within the function getConst() are 0x7ffdcd2381c8 and 0x7ffdcd2381cc, which are both descending comparing to variables within the main() function. Since main functions calls getConst() function, shouldn't location of getConst() be on top of the stack to main()?
Within getConst() function, y is a const reference to 10. As far as I understand it, the procedure is that, a temporary int variable is created with a value of 10, and y references to it. As seen in the output of the program, both y and t point to the same memory location. However the temporary variable is a variable defined in stack, shouldn't it be cleaned up after getConst() function returns? If so, how can t still get the correct value?
Your code has undefined behaviour as it is returning a reference to a temporary variable so anything could happen.
However what is actually happening is probably that the returned reference is basically a pointer, the memory pointed to is no longer valid but the pointer itself is just a number so it is unsurprising that you are able to print its value. Printing the value of the reference will probably work as the runtime doesn't "clean up" deallocated stack memory, that would be a waste of time, when the memory is re-used it will be re-initialised. If you call a new function containing uninitialised variables it wouldn't be surprising if they also have the same values as set in getConst. This of course is all undefined behaviour.
Traditionally heap memory grew up from the bottom of the memory and stack grew down from the top, when the two met your program was out of memory. With modern virtual memory schemes this isn't literally the case any more but the stack is still generally a fixed size block of memory which is used from the end back to the front so it is not unusual for new stack allocations to have lower addresses than old ones. This is what makes overflowing stack variables so dangerous, you aren't overwriting unused memory you are actually overwriting variables earlier in the stack.
I'm returning an void* pointer to a chunk in memory in this function:
memory.cpp:
int mem[1000];
int* pointers[100];
int start_index = 100;
void* allocate(int size) {
pointers[0] = &mem[start_index];
return (void *) pointers[0];
}
main.cpp:
int* arr = (int*) allocate(50); // allocate array of size 50 starting at mem[100]
arr[0] = 62; // changes mem[100] to 62
Now say I wanna make the user of this function use different location of mem array, without the user of allocate function being notified (assuming it'd be no problem we lose the data).
Can't I do this?
memory.cpp:
pointers[0] = &mem[200];
After this line is executed in memory.cpp, I want arr[0] point to mem[200].
Is that possible without changing the prototype of allocate function?
Thanks
No, you can't. You would need to return a pointer-to-a-pointer (void**) and make it absolutely clear to clients of the allocate function that they are not allowed to create aliases to the memory. Anyways, this is a very bad idea, you'll run into problems left and right (e.g. what if your client uses in-place new to allocate a non-POD object in that memory?)
Yes you can change a pointer to point at something else anytime.
However, this will only change the pointer you assign to, not other places using the old pointer. So if some code saves the returned value from your allocate function, and you later change pointers[0] to point to something else, the old saved pointer will not change.
Memory Management : scope and local pointer variable
Q. In terms of Memory Management, What is the error in the following code?
char* secret_message()
{
char message_buffer[100];
char* text = "Hey man!";
int n = 0;
while (text[n] != '\0')
n++;
for (int i = 0; i <= n ; i++)
message_buffer[i] = text[i];
return message_buffer;
}
Answer.
I think message_buffer is local variable
that is automatically reclaimed after function ends.
This function returns a reference to an invalid memory location
, since message_buffer disappears right after return statement.
Is it correct?
Please let me know.
Thanks,
Answer. I think message_buffer is local variable that is automatically reclaimed after function ends. This function returns a reference to an invalid memory location , since message_buffer disappears right after return statement.
Yes, it is correct. message_buffer is allocated on stack, its memory will be deallocated when the function exits. the pointer will points to release memory.
BTW:
char* text = "Hey man!";
should be
const char* text = "Hey man!";
in modern C++.
message_buffer is automatic variable whose scope is within the function only.
this variable either should be declared in main function or declared as static variable within the function.
You are correct. This produces undefined behaviour.
This question already exists:
Closed 11 years ago.
Possible Duplicate:
c++ warning: address of local variable
char* strdup(const char* s)
{
char dup[strlen(s)];
for (int i = 0; i<strlen(s); i++)
{
dup[i]=s[i];
}
return dup;
}
This function is supposed to hold the new array that has been read backwards plus another slot. When I compile it I get the error "warning: address of local variable 'dup' returned" and when I run the program it returns the memory address.
char dup[strlen(s)] defines a local stack variable; this goes out of scope when the function ends, so any attempt to access it after that will result in undefined behaviour.
Your options are:
Use a heap variable (obtained using new). You will have to remember to delete it at some point.
Have the function write into an existing buffer, provided by the caller (e.g. void strdup(char *out, const char *in)).
Use C++ constructs like std::string, which do all the hard work for you.
As you have marked your question "C++", I strongly recommend Option #3.
Your definition specifies an char array pointer as its return type but you initialize a char array inside your function and try to return it. Try this:
char* strdup(const char* s)
{
char *dup = new char[strlen(s)];
for (int i = 0; i<strlen(s); i++)
{
dup[i]=s[i];
}
return dup;
}
The problem is that you never allocate dup on the heap, so when you exit the stack frame, dup will automatically be removed with the stack frame. This means that it's not possible to have a valid reference to dup, as it ceases to exist once you exit the function.
This should work:
char* strdup(const char* s)
{
char* dup = new char[strlen(s)];
for (int i = 0; i<strlen(s); i++)
{
dup[i]=s[i];
}
return dup;
}
EDIT: when you are done, don't forget to use 'delete' to free the memory ;)
you can't return dup[] because, as it is, it's a local variable and won't be valid outside the function (well, the memory it points to won't be valid anymore). You have to call something like malloc(), which allocates memory on the heap (space visible by all your app)
char* strdup(const char* s)
{
char dup[strlen(s)]; // defines *local* variable on *stack*
for (int i = 0; i<strlen(s); i++)
{
dup[i]=s[i];
}
return dup; // returning dup[0] = dup address
}
You are returning address of local variable, created on stack. When you return from the function the stack will be rewind and your dup variable gone.
The line
char dup[strlen(s)];
will not work in C++. Arrays need a constant size specified at compile time; strlen(s) is a variable.
As far as your actual warning is concerned, it is a bad practice to return a pointer to a local variable to the caller; since the local variable (in this case, the array dup) is allocated on the stack, when the function returns, it is deallocated, and hence, the returned pointer may be invalid. Compilers are designed to catch such errors and flag a warning saying that this could be a potential source of problems.
The dup variable is an array of char and is allocated on the stack rather than the heap (via new or malloc). As soon as the stack frame is left (that is: the function is left) this is undefined memory that will be overwritten by other things soon.
You need to turn dup into a char * and use new or malloc to allocate the necessary memory.
I thought I was fairly good with C++, it turns out that I'm not. A previous question I asked: C++ const lvalue references had the following code in one of the answers:
#include <iostream>
using namespace std;
int& GenX(bool reset)
{
static int* x = new int;
*x = 100;
if (reset)
{
delete x;
x = new int;
*x = 200;
}
return *x;
}
class YStore
{
public:
YStore(int& x);
int& getX() { return my_x; }
private:
int& my_x;
};
YStore::YStore(int& x)
: my_x(x)
{
}
int main()
{
YStore Y(GenX(false));
cout << "X: " << Y.getX() << endl;
GenX(true); // side-effect in Y
cout << "X: " << Y.getX() << endl;
return 0;
}
The above code outputs X: 100, X:200. I do not understand why.
I played with it a bit, and added some more output, namely, a cout before the delete x; and a cout after the new x; within the reset control block.
What I got was:
before delete: 0x92ee018
after new: 0x92ee018
So, I figured that static was silently failing the update to x, and the second getX was playing with (after the delete) uninitialized memory; To test this, I added a x = 0; after the delete, before the new, and another cout to ensure that x was indeed reset to 0. It was.
So, what is going on here? How come the new returns the exact same block of memory that the previous delete supposedly free'd? Is this just because that's what the OS's memory manager decided to do, or is there something special about static that I'm missing?
Thank you!
That's just what the memory manager decided to do. If you think about it, it makes a lot of sense: You just freed an int, then you ask for an int again... why shouldn't the memory manager give you back the int you just freed?
More technically, what is probably happening when you delete is that the memory manager is appending the memory block you freed to the beginning of the free list. Then when you call new, the memory manager goes scanning through its free list and finds a suitably sized block at the very first entry.
For more information about dynamic memory allocation, see "Inside storage allocation".
To your first question:
X: 100, X:200. I do not understand why.
Since Y.my_x is just a reference to the static *x in GenX, this is exactly how it supposed it to be - both are referencing to the same address in memory, and when you change the content of *x, you get a side effect.
You are accessing the memory block that is deallocated. By the c++ standard, that is an undefined behaviour, therefore anything can happen.
EDIT
I guess I have to draw :
You allocate the memory for an int, and you pass the object allocated on the heap to the constructor of Y, which stores that in the reference
then you deallocate that memory, but your object Y still holds the reference to the deallocated object
then you access the Y object again, which holds an invalid reference, referencing deallocated object, and the result you got is the result of an undefined behaviour.
EDIT2
The answer to why : implementation defined. The compiler can create new object at any location it likes.
i test your code in VC2008, the output is X: 100, X: -17221323. I think the reason is that the static x is freed. i think my test is reasonable.
This makes perfect sense for the code.
Remember that it is your pointer that is static, so when you enter this function a second time you do not need to make a new pointer, but ever time you enter this function you are making a new int for the pointer to point to.
You are also probably in debug mode where a bit more time is spent giving you nice addresses.
Exactly why the int that your pointer points to is in the same space is probably just down to pure luck, that and you are not declaring any other variables before it so the same space in memory is still free