I have noticed that if i create a pointer in a function, it won't let me set a value to it.
for example:
int func() {
int* pointer;
*pointer = 0 //error I get: "Exception: STATUS_ACCESS_VIOLATION"
return *pointer;
}
I get that not letting you set a pointer in the function because if I use a normal int it works:
int func() {
int notAPointer;
notAPointer = 0;
return notAPointer;
}
Can anyone explain to me why that is?
You haven't assigned any memory for your pointer to point to.
That means that dereferencing the pointer (*pointer) causes undefined behavior (like a crash in your case). You need to initialize the pointer before dereferencing it:
int* pointer = new int;
(And afterwards, delete pointer; to not leak the memory. Always delete everything you get from new.)
Also, pointers don't have to point to dynamically allocated data (acquired by a call to new), you can point to automatic (stack) variables too:
int func() {
int valueOnStack = 42;
int* pointer = &valueOnStack;
*pointer = 0;
return *pointer;
}
Because when you declare pointer it is pointing to a completely arbitrary memory location. You can't just write to any old piece of memory.
You need to allocate memory for it first:
int* pointer = new int;
*pointer = 0;
Or just:
int* pointer = new int();
The pointer pointer is uninitialized and points to a random location in memory when you declare it. It could be pointing into the system stack, or the global variables, or into the program's code space, or into the operating system. When you say *pointer = 0;, the program will simply try to write a 0 to whatever random location pointer points to.
The program may explode immediately, or may wait half an hour and then explode, or it may subtly corrupt data in another part of your program and you may never realize it. This can make this error very hard to track down. Make sure you initialize all pointers to a valid address before dereferencing them.
pointer does not point to anything following int* pointer;
So the behaviour of dereferencing it is undefined.
If you'd written
int n;
pointer = &n;
then you could dereference it.
Altenatively, you can allocate memory to it from the heap:
pointer = new int;
But you must remember to call delete pointer; else you'll leak memory.
This code is completely valid inside a function:
int *pointer = 0;
BUT, it would be the same as setting a pointer to the NULL macro.
If you try to set another value the compiler is going to complain that there is no valid conversion from int to int*:
int *pointer = 1; // Error
However, if you want to assign a value to the pointer, follow TartanLlama's answer using new and delete. Allocate memory first and then assign a value:
int *pointer = new int;
*pointer = 1; // OK
// delete when appropriate
Related
I was just a little confused why the same memory address was being printed when I attempted to delete a newly allocated variable through a function, I am guessing that no memory was leaked or pointer dangled.
The same memory address was printed.
#include <iostream>
using namespace std;
void deallocater(int *p)
{
delete p;
p = nullptr; // memory deleted and no dangling pointer right?
}
int main()
{
int *x = new int(1);
cout<<x;
deallocater(x);
cout<<endl<<x; // why is the same memory address being printed?
return 0;
}
I'm assuming that the function worked successfully
Calling the function
void deallocater(int* p)
{
delete p;
p = nullptr;
}
via
deallocater(x);
copies the value of x to p. Thus within deallocater() the local variable p is assigned nullptr. However, the variable x of the calling program is not altered.
You may achieve what you appear to want by taking the argument by reference:
void deallocater(int* &p)
{
delete p;
p = nullptr;
}
However, memory allocation and de-allocation should not be split apart into different and unrelated functions to avoid the danger of dangling pointers and/or memory leaks. Instead, good C++ code contains hardly any delete statements and few new statements (to initialize smart pointers), but instead use standard library constructs (containers and smart pointers) for memory management.
The code cannot change the content of the pointer p in deallocater(), thus it still shows the same value when printed. After the call p still has the same (pointer) value, but the memory it points to is freed. This is known as a "dangling reference".
To update the pointer, use a double-pointer, or a reference to a pointer:
void deallocater(int **p)
{
delete *p;
*p = nullptr; // memory deleted and no dangling pointer right?
}
int main()
{
int *x = new int(1);
cout<<x;
deallocater( &x );
cout<<endl<<x; // why is the same memory address being printed?
return 0;
}
If we have a function like this:
int* foo()
{
int *x;
x = new int;
delete x;
return x;
}
We need to return a pointer in a function, but what we have learned is we need to delete a space in the final.
If we delete x first as above, then is it meaningful to return x in the final line? Because the x does not exist anymore.
But if we don't delete x before return, the function will be finished.
How can we do?
Or we don't really need to delete a space which was allocated in the memory?
You do need to delete the pointer at some stage, but that does not have to be in the same function scope where you new it. It can happen outside of your function, which I think is what you're trying to achieve.
int* foo()
{
int *x;
x = new int;
return x;
}
int *px = foo();
// use px in some way
delete px;
if we delete x first as above, then is it meaningful to return x in
the final line? because the x does not exist anymore.
Two things here, first no it is not meaningful to return x after delete x; and secondly, deleting x won't delete the x itself, it will only free up the memory to which the x points to.
or we don't really need to delete a space which was allocated in the
memory?
Wrong. You need to free up every dynamically allocated memory location.
but if we don't delete x before return, the function will be finished.
how can we do ?
What you can do is declare the pointer outside the function and then after you have returned the pointer x from the function, then you can delete it anywhere outside that function which returned the pointer.
Tip:
Consider using Smart Pointers because along with other benefits, one of the biggest benefit of using Smart Pointers is that they free up the allocated memory automatically and save you the headache of freeing up the memory explicitly.
There is absolutely no reason at all to delete the pointer before returning it. The only thing you will get is the memory address to a piece of memory that was allocated but no longer is.
It would make sense in this code:
main()
{
int *ptr = foo()
cout << "The memory address that function foo got "
<< "allocated to a local pointer is " << ptr << endl;
}
But come on, who would ever want to write such a thing?
It is, however perfectly ok to delete after the function call, like so:
int* ptr = foo();
delete ptr;
What you need to understand is that delete does not remove a pointer. What it does is to say "I (the program) am done with whatever this pointer is pointing to. You (the os kernel) can use it for anything now. I will not do anything more with that address. I promise." to the operating system. You do not have to have one delete for every pointer. This is completely ok, and causes no memory leaks:
int *p=new int;
int *a[3]={p, p, p};
int n;
cout << "Via which pointer in array a do you "
<< "want to delete the allocated memory? ";
cin >> n;
delete a[n];
It is pretty silly code, but it shows my point. It is not about the pointer. It's about what the pointer is pointing at.
And remember one thing. A pointer does not get the value NULL when you delete it. You have to take care of that separately.
Variables declared in the scope (between the {} ) of the functions are distroyed when leaving the function, as they are built on the stack memory of the function.
When using new(), memory is allocated on the heap, another memory space independant from the function.
This memory won't be freed before you delete the pointer pointing this memory, that's why once using a new(), you'll have to get the pointer deleted before your app returns.
Returning a deleted pointer doesn't make sense unless you want your application to crash. Dereferencing (accessing) a deleted pointer can lead to application crash or memory corruption.
If the purpose of your function is to provide a valid pointer on some type,
the delete will have to occur outside of the function, once you wont need to use the variable anymore.
Two last tips:
don't delete a pointer twice, this would cause a crash.
assigning 0 to a deleted (or non allocated) pointer can be a guard:
ex:
int * pt = 0;
pt = new int;
*pt = 12;
delete pt;
pt=0;
if (pt==0) {
// the pointer doesn't point to anything, and we can test it safely
}
/* ... */
if (pt!=0) {
delete pt; //this second delete wont occur if pt is null (==0)
pt=0;
}
Is returning a pointer declared inside the function considered bad practice? Example:
int* foo(void)
{
int * ret_val = 1234;
return ret_val;
}
I believe you're suppose to use:
static int * ret_val = 1234;
But then again, wouldn't it still be considered bad practice to return memory outside of your scope?
Returning a pointer isn't a problem as long as it points to memory that is still in scope, such as dynamically allocated memory, global data, or local variables that still exist further up the call stack.
The problem with the above code is that you're dereferencing a pointer without assigning anything to it. This: *ret_val = 1234; assigns the value 1234 to the address that ret_val points to, but ret_val wasn't assigned anything.
If on the other hand you did this:
int* foo(void)
{
int * ret_val;
ret_val = malloc(sizeof(int));
*ret_val = 1234;
return ret_val;
}
That is fine since you're returning a pointer to dynamically allocated memory.
The primary culprit is
*ret_val = 1234;
is applied with an uninitialized pointer.
I believe you're suppose to use:
static int* ret_val;
No, to fix that you could use
int* foo() {
static int_val = 1234;
return &int_val;
}
But it's arguable if that's what you really want. All callers of that function will share the same instance of int_val.
It's a really bad practice if your return a pointer to a local variable, because you will have a dangling pointer.
int* foo(void)
{
int a = 1337;
return &a; //Don't do this!
}
But sometimes it could be useful:
int* copy_array(int *array, int size)
{
int *v = (int*) malloc (size * sizeof (int));
//..copy the array..
return v;
}
Anyway, you should avoid returning pointers, so there is no risk of memory leaks.
Aside from your use of ret_val without it being allocated, returning a pointer from a function is fair practice, though it takes special care:
Don't return a pointer to a local variable, as it will be destroyed when the function exits and cause undefined behavior if dereferenced
If the function allocates memory, it is the responsibility of the caller function to ensure that the pointer is deallocated when it is no longer needed, to avoid memory leaks
If the function is processing an array in the form of a pointer, it needs to be aware of the size of the array to avoid undefined behavior, typically as an extra size parameter or a global constant
A pointer is like a shortcut or a hyperlink. Creating just a shortcut does not install a program. Creating a hyperlink does not magically sets up the whole website.
Same with a pointer: a int* is a pointer to an integer. It is not the integer itself. As such you must make sure that the pointer points to something meaningful before you try to follow the pointer.
One way of doing so is to create an integer and the sets a pointer to point to it:
int* ret_val = new int;
This will create an integer (the new operator), and then sets the ret_val pointer to point to it.
Objects created through new exist until you explicitly destroy them through delete or when your application ends. For that reason, if you have new int in a function, it is safe to access it even if the function ends.
What would be dangereous, and probably caused your concern, is if you would set the pointer ret_val not to a new integer, but to an existing local variable, i.e.
int myInteger;
int* ret_val = &myInteger;
In such scenario, ret_val points to a local variable myInteger which gets destroyed when the scope containing the declaration ends. You end up with a dangling pointer, referencing stuff that does not exist (think: broken hyperlink). Using such a pointer can lead to undefined behavior. It may crash your program, but it may as well silently accept it, modifying some random space in memory.
So, a function of the shape:
int* foo(void)
{
int* ret_val = new int;
*ret_val = 1234;
return ret_val;
}
is safe to use. It is not necessarily a good practice: the user of such function must know that it creates a new integer, that later - at some point - someone should delete. Functions that do that typically highlight such behavior in some way, e.g. through its name. For example, allocateInt() makes it clear that it created something that later should be delete. In contrast, getInt() suggests that the integer already exists and nothing new is created.
You should consider:
int *foo() {
int *ret_val = new int(1234);
return ret_val;
}
instead of (bad code):
int* foo(void)
{
int * ret_val;
*ret_val = 1234;
return ret_val; // dangling pointer!
}
otherwise you will have dangling pointer (the second example).
Obviously don't forget to release the memory.
You should also consider using smart pointers:
https://en.wikipedia.org/wiki/Smart_pointer
As you specified both C++ and C languages the above code is in C++ (operator new), please refer to (e.g.) #Mattia F. answer for ANSI C.
If I go...
int *foo = new int;
foo += 1;
delete foo;
Most of the time it crashes. Is there a reason for this? I'm trying to have the pointer point one spot forward (4 bytes). Thanks.
Edit (six months later): This was the first question I asked on SO, and it was a silly question and deserved the downvotes. It can be deleted if it's of no use to learners. I was indeed talking about allocating an int of four bytes on the heap, then moving the pointer four bytes forward, and then deleting the int pointer, essentially deleting God knows what, leading to undefined behaviour. Thanks for your help.
The only thing you can safely pass to delete is something you got when you called new, or nullptr, in that case the delete won't do anything.
You changed the value of the pointer - therefore it isn't "something you got when you called new"
You must pass to delete the value that new returned. You don't do that.
I think that you are confused as to what you are passing to delete. I think that you believe that delete foo will delete the memory associated with the variable. It doesn't. It deletes the memory whose address is stored in foo.
As an example, this is legitimate:
int* foo = new int;
int* bar = foo;
delete bar;
What matters is not the name of the variable, but rather the value of the variable.
Here's another example:
int* arr = new int[10];
int* ptr = arr;
for (int i; i < 10; i++)
{
*ptr = i;
ptr++;
}
delete[] arr;
In order to perform pointer arithmetic, and retain the address returned by new[], we introduced an extra variable. I used an array because it doesn't make sense to perform arithmetic on a pointer to a single value.
Note that in the code above, it could be written more clearly using arr[i] = i and so avoid the need for a second pointer variable. I wrote it as above to illustrate how you might code when pointer arithmetic is the right option.
I have a small homework problem.
The following code is given:
int * p;
p = new int;
*p = 5;
The question is: Why is it useless to do
p = 0;
delete p;
but usefull to do
delete p;
p = 0;
?
In my opinion, both is useless. If an object is deleted, no new value can be assigned.
I also get in both cases a Segmentation fault.
For Why it is useful for the following:
delete p;
p = 0;
Quoting from stroustrup's answer: Why doesn't delete zero out its operand?
Consider
delete p;
// ...
delete p;
If the ... part doesn't touch p then the second "delete p;" is a serious error that a C++ implementation cannot effectively protect itself against (without unusual precautions). Since deleting a zero pointer is harmless by definition, a simple solution would be for "delete p;" to do a "p=0;" after it has done whatever else is required.However, C++ doesn't guarantee that.
One reason is that the operand of delete need not be an lvalue. Consider:
delete p+1;
delete f(x);
Here, the implementation of delete does not have a pointer to which it can assign zero. These examples may be rare, but they do imply that it is not possible to guarantee that any pointer to a deleted object is 0.'' A simpler way of bypassing thatrule'' is to have two pointers to an object:
T* p = new T;
T* q = p;
delete p;
delete q; // ouch!
C++ explicitly allows an implementation of delete to zero out an lvalue operand, and I had hoped that implementations would do that, but that idea doesn't seem to have become popular with implementers.
If you consider zeroing out pointers important, consider using a destroy function:
template<class T> inline void destroy(T*& p) { delete p; p = 0; }
Consider this yet-another reason to minimize explicit use of new and delete by relying on standard library containers, handles, etc.
Note that passing the pointer as a reference (to allow the pointer to be zero'd out) has the added benefit of preventing destroy() from being called for an rvalue:
int* f();
int* p;
// ...
destroy(f()); // error: trying to pass an rvalue by non-const reference
destroy(p+1); // error: trying to pass an rvalue by non-const reference
Recall that deleting 0 is allowed. Therefore, when you do this
p = 0;
delete p; // Deleting zero is ignored
you throw away the old value of p (thus creating a memory leak), and then call delete 0, which is ignored.
When you do this, however
delete p;
p = 0;
you use the old value first (to de-allocate the int), and only then zero it out. This makes sense, because the old value of p becomes both useless and dangerous as soon as delete is executed.
This sets the pointer to null and then calls delete:
p = 0;
delete p;
It is like saying
delete 0;
I think what you are thinking is that it is setting the int that p points to to zero, but that would be done like this:
*p = 0;
p = NULL;
and
p = 0;
In the above case you are assigning value to the pointer and not to the object it points to.
Are one and the same. delete function is used to free the memory allocated dynamically to an object.
When you say
delete p;
p = 0;
It is like saying free the memory allocated to the pointer p and
then you are saying assign the pointer to NULL. Which is right.
In the other case when you do this
p = 0;
delete p;
You are saying assign the pointer to NULL first. Now the pointer p
is not pointing to any valid dynamically assigned memory. So later
when you say delete p the compiler cannot find any memory to free
and hence throws a segmentation fault.
In the first case, you are assigning the value of the POINTER p to be '0', not the value of the int that p points to. That's why it is both useless (will in fact cause a memory leak), and causes a seg fault when you try to delete from memory address '0'. EDIT - actually I just learned that the segfault is not caused by the 'delete 0', which is ignored according to the standard, so something else is causing that.
In the second case you are freeing the memory / object pointed to by p (which should be fine), and then assigning the pointer to have a value '0', which should also be Ok, so not sure why you are seg faulting there? In terms of usefulness, it used to be considered good practice to set free'd pointers to a null or '0' value so you can test for that before de-referencing them.