I wanted to ask, if I have a pointer pointing at some struct, but then I free(struct) then if I dereference the pointer, will it be pointing to NULL? As in can I check, pointer != NULL or is this undefined?
Thanks!
Calling free() on the pointer does not change the pointer value. It will still point to the same memory that no longer belongs to your application. You should always assign NULL to a free'd pointer immediately after you free it to ensure that you don't use it again.
void *p = malloc(10); // p points to allocated memory
free(p); // p still points to invalid memory
p = NULL; // good practice
Consider the below code
int main()
{
int *p = (int *)malloc(sizeof(int) * 10);
free(p);
}
Here variable p is a local variable of a function main. Size of this variable will be 4 bytes(in 32bit m/c) or 8 bytes(in 64 bit m/c). Now we are allocating memory for storing 10 integer elements and that address is stored in variable p. Now we are calling free function to which we are passing the dynamic memory address which is stored in the local variable p. Now free function will free the memory and it will not be able to assign NULL to the variable p. Because we passed address as value, not reference to the pointer.
We can define a wrapper function for free like below
void myfree(void **p)
{
free(*p);
*p = NULL;
}
int main()
{
int *p = (int *)malloc(sizeof(int) * 10);
myfree(&p);
}
Or we can define macro function also
#define MYFREE(x) \
free(x); \
x = NULL;
It's undefined. C does not define what it does with the contents of the pointer, although most implementations do nothing.
Take a look at this page.
It clearly says:
Notice that this function leaves the value of ptr unchanged, hence it
still points to the same (now invalid) location, and not to the null
pointer.
Note that it is up to you to make sure that pointer is not dereferenced after being freed.
Related
For example:
void heaptest(){
int *a;
a=(int*)malloc(1024*4);
int i=1024;
while(i--){
*a=i;
//printf("%d",*a);
a++;
}
free(a);
}
When the 'a' was used as a pointer, assume it points to address "0x20000". And the scope of this heap area is from 0x20000 to 0x21000. totally 4096 bytes.
after the while loop, the 'a' was pointed to 0x21004, which is actually out of the scope of the defined heap. if we free the heap using
free(a)
Will this heap be freed successfully?
For my observation, when I use this func in Visual Studio. it will show
Invalid address specified to RtlValidateHeap
and the value of a is 0x21004 before the free() operation whenever whether there is a printf() function in the while loop.
When I use this function on Keil-MDK for STM32F7(Cortex M7), it shows nothing but before the free operation. the value of 'a' will become 0x00000;
But when I add the printf() function shown in the code. the value of 'a' will back to the initial value 0x20000.
So, the final question is, could we change the value of the heap pointer? or assign it back to the initial value every time before the free() operation?
Will this heap be freed successfully?
It is impossible to say. You invoke undefined behavior by passing a pointer value to free() that was not returned by malloc() or one of the other allocation functions. That could turn out to manifest as freeing the block into which the pointer points, but more likely it produces an error, or worse: silent memory corruption.
Note in particular that it is the pointer value that matters. The variable, if any, in which you store the pointer value has nothing directly to do with it.
could we change the value of the heap pointer?
In the sense that the pointer is a value, no, you can no more change it than you can change the value 1. But you can cause a variable in which that value is stored to instead contain a different value. You may even be able to do so in a way that allows you to recover the original value, so as to retain the ability to free the allocated memory.
You need to free the address your were given. What you do to the code's variables in between does not matter.
This is valid:
char * p = malloc(42);
p++;
p--;
free(p);
This as well:
char * p = malloc(42);
char * q = p:
/* p += 43; */ /* Invokes UB, as making q point more then just one past the object. */
q += 42; /* Just one past the allocated memory. */
q -= 42;
free(q);
This isn't
char * p = malloc(42);
p++;
free(p);
This neither:
char * p = malloc(42);
p--;
free(p);
An address passed to free must have been obtained as the return value of malloc/calloc/etc. Passing any other pointer invokes undefined behavior.
From the MSDN page for free:
The free function deallocates a memory block (memblock) that was
previously allocated by a call to calloc, malloc, or realloc. The
number of freed bytes is equivalent to the number of bytes requested
when the block was allocated (or reallocated, in the case of realloc).
If memblock is NULL, the pointer is ignored and free immediately
returns. Attempting to free an invalid pointer (a pointer to a memory
block that was not allocated by calloc, malloc, or realloc) may affect
subsequent allocation requests and cause errors.
Keep track of the original pointer so you can later pass it to free:
void heaptest(){
int *a, a_sav;
a=(int*)malloc(1024*4);
a_sav = a; // save the original pointer
int i=1024;
while(i--){
*a=i;
printf("%d",*a);
a++;
}
free(a_sav); // free the saved pointer
}
Calling free with an argument that does not point to an adress allocated via malloc, calloc or realloc is undefined behavior. You have absolutely zero information on what it will do. Try something in this form.
void heaptest(){
// Declare a const to make sure we free the right adress in the end
int * const a = (int*)malloc(1024*size_of(int));
int i=1024;
do {
// This will loop from a[0] to a[1024] which is what I assume you meant to do
a[1024-i] = i;
} while (--i);
free(a);
}
It's hard to say if this program does what you wanted. You can change i or the index or the right hand side of the assignment to suit your needs but don't do the loop like you did because it's way more error-prone.
In the following example, function func() returning an address of a local pointer variable to main() function. It's working fine in GCC.
So, Is it well-defined behaviour?
#include <stdio.h>
#include <stdlib.h>
int *func(void);
int *func(void)
{
int *p;
p = malloc(sizeof *p);
*p = 10;
return p;
}
int main()
{
int *ptr = func();
printf("%d\n",*ptr);
return 0;
}
No, you do not return a pointer to (address of) a local variable. That would be doing something like
int i = 10;
return &i;
Instead you return a pointer to an object allocated on the heap.
You do have a memory leak though, since you don't free the memory anywhere. Calling free should be done by the code calling your function (unless it in turn return the pointer value, where the responsibility continues upt he call-chain).
Inside func(), p is a pointer to memory allocated by malloc() (or to potentially allocated memory, since malloc() can fail, returning a null pointer; this should be checked for). If successful, this memory allocation will persist until it is explicitly freed.
The value of p is returned to the calling function, main() in this case. p is either a pointer to a successful allocation, or is a null pointer, and the returned value (which is temporary, and not an lvalue) is then assigned to ptr. So, the allocated storage can be accessed through ptr, which is a copy of the value held by p before func() returned, though the lifetime of p itself has ended now that func() has returned.
Of course ptr should be freed when it is no longer needed to avoid memory leaks. And, there is potential undefined behavior here if malloc() fails, since then ptr is a null pointer.
This is perfectly valid.
What is not guaranteed is what will happen to the variables on the stack frame once a function returns and the stack frame shrinks.
What you are returning is an address to some malloced memory and not the address of a local variable (allocated on the stack). This is very similar to how strdup() works. Here's an implementation of strdup() taken from here.
char *
strdup(str)
const char *str;
{
size_t len;
char *copy;
len = strlen(str) + 1;
if (!(copy = malloc((u_int)len)))
return (NULL);
bcopy(str, copy, len);
return (copy);
}
One obvious downside of this (as mentioned by "Some programmer dude") is that the responsibility of freeing is passed on to the caller.
This is a valid and correct code, although bit confusing.
The func is allocating memory of size int. The allocation is done via de-referencing a pointer variable of type int.
Alter allocation the integer value of 10 is set in the memory. 10 should be set as integer (can be compiler dependent). But definitely will not be of greater than the size of integer so should be safe operation.
After that the pointer value is returned by the function.
In main() the returned pointer is set to another integer pointer. This points to the original memory allocated by malloc().
After that the de-referenced integer pointer is printed in the printf() statement. This will print the value of 10.
What is missing is the free() call, which is not the good behaviour in here.
This can be a good academic exercise for kids.
I am trying to give a value to a pointer.
this code works fine
int i =5;
int *ptr ;
ptr = &i;
printf(" %d\n",*ptr);
but this code shows an error
int i =5;
int *ptr ;
*ptr = 5;
printf(" %d\n",*ptr);
can someone explain this to me?
int *ptr gets initialized to a random location, which possibly points to invalid memory, and you try to write 5 to that location.
When you declare int *ptr, you're creating a variable called ptr which can hold the address of an int. When you dereference it in *ptr = 5, you're saying "store 5 in the address that ptr points to" - but as ptr is uninitialised, where it points to is undefined. So you're invoking undefined behaviour.
An int * does not store an int, but just an address that points to one. There still has to be a real int at that address.
If you want to allocate an int that exists outside of the local scope, you can use malloc. A simple conversion of your example without error checking:
int *ptr = malloc(sizeof(int));
*ptr = 5;
printf(" %d\n",*ptr);
If you do use malloc, just remember to free the allocated memory when you're finished:
free(ptr);
The second version assigns 5 to the memory pointed to by ptr, but you haven't yet initialized ptr to point to a known location.
So it writes the value to the memory at whatever address happens to be in ptr, which is whatever was in memory where ptr was declared.
You can't deterrence a pointer that doesn't point to somewhere you own.
int* ptr;
That allocates space for the pointer, but it doesn't allocate space for the chunk the pointer points to.
Also, since it's not initialized, ptr has an indeterminate value. This means that not only does it likely point to something you don't own, it also would be rather difficult to check if it's a valid pointer. It's usually a good idea to initialize pointers to either NULL (or nullptr if available) or an actual location (like you did in the first example).
The following code works fine in ideone but it gives a runtime error in codeblocks IDE . Is my IDE broken or is there any programming language specific issues .
#include<stdio.h>
int main(){
int *pointer;
int num = 45;
*pointer = num;
printf("pointer points to value %d", *pointer);
return 0;
}
replace this
*pointer = num;
by
pointer = #
Your pointer should be pointed to a memory space before assignment of value to it.
When you define pointer in this way:
int *pointer;
This meas that you have defined pointer but the pointer is not yet pointing to a memory space. And if you use the pointer directly without pointing it to a memory space (like you did in your code) then you will get undefined behaviour.
pointing the pointer to amemory space could be done by one of the following way:
1) pointing to a static memory
int num;
int *pointer = #
num is an int defined as a static. So the pointer could be pointed to the num memory
2) pointing to a dynamic memory
int *pointer = malloc(sizeof(int));
the pointer could be pointed to a dynamic memory. the dynamic memory could be allocated with malloc() and when the memory became useless we can free memory with free(pointer)
Assign address of num to pointer as pointer is supposed to hold address not value. You can read more about pointers here
pointer = #
Change value of variable through pointer
*pointer = 11;
First,you have defined a pointer by "int *pointer".
Then, you try to use "*pointer = num" to realize indirect access —— assign num's value to the memory space which the pointer "pointer" has pointed to.
OK, here is the problem! From your codes, you only have defined a pointer, but you have not made it pointed to a memory space. Making indirect access without doing it is very dangerous. So, you see the runtime error.
Now, you should add "int value;pointer = &value;" to your codes. It will make the pointer "pointer" point to "value". And you can assign "num" to "value" through indirect access "*pointer = num".
In my opinion, you should distinguish definition and indirect access when you study pointer.
I'm a person with poor English. This is my first answer in stack overflow. I hope that my answer can help you. Thank you.
First of all u should initialize the pointer as to which its trying to point then use it to modify the pointed value..as...
pointer=#
now use the pointer to change or access the value to which its pointing.
As I know, when a pointer is passed into a function, it becomes merely a copy of the real pointer. Now, I want the real pointer to be changed without having to return a pointer from a function. For example:
int *ptr;
void allocateMemory(int *pointer)
{
pointer = malloc(sizeof(int));
}
allocateMemory(ptr);
Another thing, which is, how can I allocate memory to 2 or more dimensional arrays? Not by subscript, but by pointer arithmetic. Is this:
int array[2][3];
array[2][1] = 10;
the same as:
int **array;
*(*(array+2)+1) = 10
Also, why do I have to pass in the memory address of a pointer to a function, not the actual pointer itself. For example:
int *a;
why not:
allocateMemory(*a)
but
allocateMemory(a)
I know I always have to do this, but I really don't understand why. Please explain to me.
The last thing is, in a pointer like this:
int *a;
Is a the address of the memory containing the actual value, or the memory address of the pointer? I always think a is the memory address of the actual value it is pointing, but I am not sure about this. By the way, when printing such pointer like this:
printf("Is this address of integer it is pointing to?%p\n",a);
printf("Is this address of the pointer itself?%p\n",&a);
I'll try to tackle these one at a time:
Now, I want the real pointer to be changed without having to return a pointer from a function.
You need to use one more layer of indirection:
int *ptr;
void allocateMemory(int **pointer)
{
*pointer = malloc(sizeof(int));
}
allocateMemory(&ptr);
Here is a good explanation from the comp.lang.c FAQ.
Another thing, which is, how can I allocate memory to 2 or more dimensional arrays?
One allocation for the first dimension, and then a loop of allocations for the other dimension:
int **x = malloc(sizeof(int *) * 2);
for (i = 0; i < 2; i++)
x[i] = malloc(sizeof(int) * 3);
Again, here is link to this exact question from the comp.lang.c FAQ.
Is this:
int array[2][3];
array[2][1] = 10;
the same as:
int **array;
*(*(array+2)+1) = 10
ABSOLUTELY NOT. Pointers and arrays are different. You can sometimes use them interchangeably, however. Check out these questions from the comp.lang.c FAQ.
Also, why do I have to pass in the memory address of a pointer to a function, not the actual pointer itself?
why not:
allocateMemory(*a)
It's two things - C doesn't have pass-by-reference, except where you implement it yourself by passing pointers, and in this case also because a isn't initialized yet - if you were to dereference it, you would cause undefined behaviour. This problem is a similar case to this one, found in the comp.lang.c FAQ.
int *a;
Is a the address of the memory containing the actual value, or the memory address of the pointer?
That question doesn't really make sense to me, but I'll try to explain. a (when correctly initialized - your example here is not) is an address (the pointer itself). *a is the object being pointed to - in this case that would be an int.
By the way, when printing such pointer like this:
printf("Is this address of integer it is pointing to?%p\n",a);
printf("Is this address of the pointer itself?%p\n",&a);
Correct in both cases.
To answer your first question, you need to pass a pointer to a pointer. (int**)
To answer your second question, you can use that syntax to access a location in an existing array.
However, a nested array (int[][]) is not the same as a pointer to a pointer (int**)
To answer your third question:
Writing a passes the value of the variable a, which is a memory address.
Writing *a passes the value pointed to by the variable, which is an actual value, not a memory address.
If the function takes a pointer, that means it wants an address, not a value.
Therefore, you need to pass a, not *a.
Had a been a pointer to a pointer (int**), you would pass *a, not **a.
Your first question:
you could pass a pointer's address:
void allocateMemory(int **pointer) {
*pointer = malloc(sizeof(int));
}
int *ptr;
allocateMemory(&ptr);
or you can return a pointer value:
int *allocateMemory() {
return malloc(sizeof(int));
}
int *ptr = mallocateMemory();
I think you're a little confused about what a pointer actually is.
A pointer is just variable whose value represents an address in memory. So when we say that int *p is pointer to an integer, that just means p is a variable that holds a number that is the memory address of an int.
If you want a function to allocate a buffer of integers and change the value in the variable p, that function needs to know where in memory p is stored. So you have to give it a pointer to p (i.e., the memory address of p), which itself is a pointer to an integer, so what the function needs is a pointer to a pointer to an integer (i.e., a memory address where the function should store a number, which in turn is the memory address of the integers the function allocated), so
void allocateIntBuffer(int **pp)
{
// by doing "*pp = whatever" you're telling the compiler to store
// "whatever" not in the pp variable but in the memory address that
// the pp variable is holding.
*pp = malloc(...);
}
// call it like
int *p;
allocateIntBuffer(&p);
I think the key to your questions is to understand that there is nothing special about pointer variables. A pointer is a variable like any other, only that the value stored in that variable is used to represent a position in memory.
Note that returning a pointer or forcing the caller to move the pointer in an out of a void * temp variable is the only way you can make use of the void * type to allow your function to work with different pointer types. char **, int **, etc. are not convertible to void **. As such, I would advise against what you're trying to do, and instead use the return value for functions that need to update a pointer, unless your function by design only works with a specific type. In particular, simple malloc wrappers that try to change the interface to pass pointer-to-pointer types are inherently broken.