I am testing kernel module that allocates memory using kmalloc to some variable and memset it's value and free.
Here is the code with zeroisation memory routine.
unsigned char *a = (unsigned char *)kmalloc(256, GFP_KERNEL);
unsigned char *b;
int i;
for(i=0;i<256;i++)
{
a[i]=(unsigned char)i;
}
// print variable a
printk("before zeroisation\n");
for(i=0;i<255;i++)
{
printk("%02x", a[i]);
}
// copy allocated address to variable b
b =a;
memset(a, 0x00, 256);
// print memset to zero
printk("memset variable a\n");
for(i=0;i<255;i++)
{
printk("%02x", b[i]);
}
free(a);
a=NULL;
// print free variable's address
printk("after zeroisation\n");
for(i=0;i<255;i++)
{
printk("%02x", b[i]);
}
and result is
before zeroization
000102030405060708090a0b0c0d0e0f ...
memset variable a
00000000000000000000000000000000 ...
after zeroization
001e7f430088ffff0000000000000000 ...
It seems free of variable makes insert value of something's address in allocated area. 001e7f430088ffff -> ffff8800437f1e00 (in little endian)
Additionaly address of pointer of b is ffff8800437f0800
I know that dynamic memory allocation in heap memory has free-list made of double-linked list.
I think this is related to memory allocation process too.
I want to know the meaning of value 001e7f430088ffff and process of within kfree function.
thanks.
b =a;
Which means both a and b points to same memory. Free any pointer will result in losing the memory from both pointers. and then this memory can contain any garbage value.
free(a);
a=NULL;
Once freed no need to assign NULL. When you free a pointer, it means it is no more pointing to any memory.
So if you need to avoid such behavior
Either don't free pointer a. Just assign it NULL or another memory
Or use memcpy(b, a, sizeof(a)); function to copy values in a. But before that you have to allocate memory to b
Related
#include<stdlib.h>
#include <stdio.h>
#include <string.h>
struct t {
int value;
};
int main (void) {
struct t *a = malloc(6*sizeof(struct t));
struct t *b = malloc(sizeof(struct t));
struct t *c = malloc(sizeof(struct t));
c->value = 100;
struct t *d = malloc(sizeof(struct t));
d->value = 100;
struct t *e = malloc(sizeof(struct t));
e->value = 100;
memcpy(b, a, sizeof(*a));
int j = 0;
while (j<6){
a[j] = *c;
j++;
}
int t = 0;
while(t < 6){
free(&a[t]);
t++;
}
free(a);
}
I'm trying to free the elements inside the array one by one. But this code cannot run so I think there might something wrong with free inside the second while loop. After I changed the second while loop to:
while(t < 6){
printf("%d",a[t].value);
t++;
}
It will run. Any idea how can I free those elements?
Thanks!
I'm trying to free the elements inside the array one by one. But this code cannot run so I think there might something wrong with free inside the second while loop.
Yes, what's wrong is the attempt to free the elements one by one.
You cannot free allocated memory in different divisions than it was allocated in. The argument to free() must be a pointer value that was previously obtained from an allocation function (and not since freed). The free() call will then free the entire block. It cannot see any subdivisions of that block that you may be using, and it would be unlikely to be able to honor them even if it could see them.
Any idea how can I free those elements?
Free the whole block at once, after you're done with all the data within. That is, just
free(a);
(And also, free(b), free(c), etc.)
One free per malloc'd block.
When you malloc, you are not grabbing memory for each struct. You are grabbing one block (per malloc call) that happens to be large enough to fit 6 structs for a and 1 struct each for the others. You can only free each block of this block at once. In this case you should be freeing a through e (which are addresses returned by malloc assuming you had enough memory).
You could if you really needed to, malloc an array of struct * then malloc blocks into those struct *, but why would you in this case where the struct is small and easily copied?
The key is this: When you allocate a block of memory, malloc (calloc or realloc) will return a pointer to the beginning address in that block. You have 2 responsibilities regarding any block of memory allocated: (1) always preserve a pointer to the starting address for the block of memory so, (2) it can be freed when it is no longer needed. free() must be passed the same address returned by malloc().
You can not provide an address from the middle of the allocated block to free(). Why? Because that will not be an address originally returned by a previous call to malloc, calloc or realloc. That is a requirement, see the man-page for free() (man 3 malloc)
The free() function frees the memory space pointed to by ptr, which must have
been returned by a previous call to malloc(), calloc(), or realloc().
So you can only make a call to free() providing a pointer holding an address that was previously allocated and returned by malloc, calloc or realloc. In your case that is a, not &a[1] ... &a[5].
If I dynamically allocated a space for a pointer, list this:
int *a = (int*)malloc(sizeof(int));
should I free a when the code is done? Thanks!
I think you have a little misunderstanding related to pointer.
Your title says:
Free uninitialized pointer ...
and your code is
int *a = (int*)malloc(sizeof(int));
The problem with this is that there is no uninitialized pointer in the code. The only pointer in the code is the variable a and it is initialized by the value returned by malloc.
Freeing an uninitialized pointer would be bad - example:
int *a; // a is an uninitialized pointer
free(a); // Real bad - don't do this
but since you actually initialize the pointer then - Yes, you must call free when your are done using the object/memory pointer a points to. It does not matter whether or not the pointed-to object (aka memory) has been assigned a value.
The general rule: For each call of malloc there must be a call of free
(Exception: If your program terminates, you don't need to call free)
int *a = malloc(sizeof(*a));
if (a)
{
/* a is now valid; use it: */
*a = 1 + 2 + 3;
printf("The value calculated is %d\n", *a);
}
/* Variable A is done being used; free the memory. */
free(a); /* If a failed to be allocated, it is NULL, and this call is safe. */
Yes.
If you successfully malloc something is is correct to free it as well.
int *a = (int *) malloc(sizeof int);
if (a != NULL)
{
/* Do whatever you need to do with a */
free(a);
}
else
{
puts("the malloc function failed to allocate an int");
}
int *a = (int*)malloc(sizeof(int));
should I free a when the code is done?
The question should be
Must I free a when the code is done?
And the answer is YES. A malloc must be accompanied by a a free statement.
free(a);
My friend and I had a discussion over freeing dynamically allocated memory. He told that a memory could be freed with realloc(), to which I denied.
Let's consider the below code:
int main()
{
int *p = (int *)malloc(sizeof(int) * 10);
int *q = (int *)malloc(sizeof(int) * 10);
free(p);
p = NULL;
realloc(q, sizeof(int) * 0);
q = NULL;
_getch();
return 0;
}
Let's assume p and q are pointing to address 0x1000 & 0x2000 respectively.
In the above code, p and q are int pointers pointing to dynamically allocated 40 bytes of memory blocks in the RAM. On executing free(p) frees the memory address (0x1000). The freed memory address (0x1000) could be used by an OS again. Then, NULL is assigned to pointer variable p to prevent p of becoming a dangling pointer.
realloc(q, sizeof(int) * 0);
realloc() simply shrinks the memory block pointed by q to zero. But q still points to the same address (0x2000), and that address is not freed. On assigning NULL value to pointer q, q now points to NULL and the address (0x2000) to which q was pointing is not freed and the link to that address (0x2000) is lost. That address (0x2000) cannot be used by OS in the future until the end of the program.
Is my understanding correct?
realloc(, 0) is implementation dependent and not equivalent to free().
That said, you might be lucky:
#include <stdio.h>
#include <malloc.h>
int main() {
char *a;
a = malloc(1024);
printf("a = %08lx\n", a);
free(a);
a = malloc(1024);
printf("a = %08lx\n", a);
realloc(a, 0);
a = malloc(1024);
printf("a = %08lx\n", a);
}
gcc version 6.1.1 20160815 [gcc-6-branch revision 239479] (SUSE Linux)
ldd --version
ldd (GNU libc) 2.23
a = 01dad010
a = 01dad010
a = 01dad010
So the second malloc, after realloc(, 0), "sees" a free block where before was a. I take it to mean that in this instance, realloc duplicates the behaviour of free. DO NOT RELY ON THIS.
realloc(q, sizeof(int) * 0);
is same as
realloc(q, 0);
The C standard in 7.22.3.5 ->2 The realloc function says :
..and returns a pointer to a new object that has the size specified by
size. The contents of the new object shall be the same as that of the
old object prior to deallocation, up to the lesser of the new and old
sizes.
But it doesn't explicitly specify what would happen if the new size is zero.
But you still have an artist pointer that could be passed to free.
Consider
char *a;
a=malloc(2*sizeof *a);
a=realloc(a,0);
// Note I'm purposely NOT using a temporary variable to store 'realloc' results
// Moreover, above is BAD practice.
free(a); // Is this permitted? YES !! Did we technically free memory above? NO !!
//Compiler will not yell at you for the above, in fact it is legal as per the standard
return 0; // No output for this one
vs
char *a;
a=malloc(2*sizeof *a);
free(a);
//You're not suppose to free(a) again.
free(a);
//Compiler will yell at you for the above.
return 0;
output
double free or corruption (fasttop): 0x0000000000915010
Conclusions
deallocation and freeing are not exactly the same things.
Both realloc and free can deallocate memory, but only free frees the memory.
That said
free(p);
p = NULL;
is the recommended way to free memory. Do check [ this ] answer.
This question already has answers here:
Using realloc to shrink the allocated memory
(5 answers)
Closed 2 years ago.
I have a question about the realloc function. Will the content of old pointer be changed after apply realloc function?
The code is
main () {
int *a, *b, i;
a = calloc(5, sizeof(int));
for (i = 0; i < 5; i++)
a[i] = 1;
for (i = 0; i < 5; i++)
printf("%d", a[i]);
printf("\n%p\n", a);
b = realloc(a, 200000 * sizeof(int));
if(b == NULL)
printf("error\n");
for (i = 0; i < 5; i++)
printf("%d", a[i]);
printf("\n");
for (i = 0; i < 10; i++)
printf("%d", b[i]);
printf("\n%p %p\n", a, b);
}
The output is
11111
0x2558010
00111
1111100000
0x2558010 0x7f29627e6010
Pointer a still point to the same address, but the content is changed.
Pointer a still point to the same address, but the content is changed.
That's because realloc() may first try to increase the size of the block that a points to. However, it can instead allocate a new block, copy the data (or as much of the data as will fit) to the new block, and free the old block. You really shouldn't use a after calling b = realloc(a, 200000 * sizeof(int)) since the realloc call may move the block to a new location, leaving a pointing to memory that is no longer allocated. Use b instead.
The value returned by realloc tells you whether it succeeded or failed.
b = realloc(a, 200000 * sizeof(int));
If it fails, it returns a null pointer, and a still points to the original unmodified chunk of memory (and of course b is a null pointer).
If it succeeds, then b points to a (possibly newly allocated) chunk of memory, and the value of a is indeterminate. If it was able to allocate the new chunk in the same place as the old one (by growing or shrinking the chunk in place), then b will be equal to a -- but testing that, or even referring to the value of a, has undefined behavior. If it has to relocate the chunk, then realloc will have done the equivalent of free(a) after copying the data. In either case, it's probably best to set a to NULL to avoid accidentally referring to its (now indeterminate) value.
Note that realloc can relocate chunk even if the new size is smaller.
A simple realloc implementation should answer your questions:
void * realloc(void * ptr, size_t desired_size) {
size_t allocated_size = _allocated_size_of(ptr);
if (allocated_size < desired_size) {
void * new_ptr = malloc(desired_size);
memcpy(new_ptr, ptr, allocated_size);
free(ptr);
ptr = new_ptr;
}
return ptr;
}
malloc and related functions don't always allocate exactly the desired size. Very often they allocate more than the desired size. There is some hidden data kept up with by the memory allocation functions which allows for a pointer that was allocated by malloc or related functions to be used to look up the memory block size that was allocated. How this is kept up with isn't necessary to understand, but some very simple implementations simply store the size in the space just before the pointer returned *(((size_t)ptr)-1).
If realloc() returns a pointer different from the one you passed in (as it will most of the time), then the pointer you passed in no longer belongs to you, and you have no business knowing or caring what becomes of it. It might change its contents, it might not. But you are no longer allowed to access it, so it can be no concern of yours.
If 'a' points a valid block of memory (from a previous malloc/realloc/calloc), then a realloc call will attempt to provide a block of memory with the new size you requested
The realloc call should be of the form *tmp = realloc (a ...
The return value from realloc must be tested
If it is NULL, realloc was unable to allocate the requested memory, and this leaves 'a' as a valid pointer
You are then responsible for handling any data pointed to by 'a' (save it / discard it) and you are responsible for free ing the memory pointed to by 'a'
If the realloc call was successful make b = tmp and now 'b' is the new pointer to the block of memory - it does not matter whether the start location is the same as 'a' or different. 'a' is no longer a valid memory allocation pointer, although further errors will depend on whether 'a' points to memory owned by your program or not - basically if a == b, 'a' can be accessed without obvious errors.
After a valid *tmp = realloc(a ... & b = tmp;:
1) If the start location of the reallocated memory was unchanged: (a == b)
it will allocate the requested memory
but run it under valgrind and you will see error messages:
Invalid free() / delete / delete[] / realloc()
Address 0x51fc040 is 0 bytes inside a block of size 256 free'd
In this case realloc could not free the memory pointed to by 'a'
and again in this case 'a' can still be accessed as it is a pointer to memory that is allocated to your progam
2) If the start location of the reallocated memory was changed: (a != b)
it will fail and Valgrind shows output like this:
address of a: 0x1e89010
address of b: 0x7f2c5893c010
a after realloc: 0x1e89010
Error in `./test15': realloc(): invalid old size: 0x0000000001e89010
and trying to access 'a' will fail - even trying to print it's value as a pointer fails, presumably because it no longer points to memory owned by the program
In other words, using 'a' after b = realloc(a ... is undefined behaviour.
The above commentary was based on using the following code:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
int *a = NULL, *b = NULL, *c = NULL;
/* initial allocation */
a = malloc(256);
if( a == NULL) return (1);
printf("address of a: %p\n", a);
/* reallocation 'b' MAY be same as 'a' - try much larger allocations */
void *tmp = realloc(a, 512);
if ( !tmp ) {
free(a);
return (1);
} else {
b = tmp;
}
printf("address of b: %p\n", b);
/* see what 'a' is now - this MAY crash the program*/
printf("a after realloc: %p\n", a);
/* 'a' may not be a valid pointer - try using it for another realloc */
c = realloc(a, 256);
/* Valgrind shows that memory could not be free'd or 'a' was not valid allocated memory */
printf("return value of c: %p\n", c);
if (c != NULL) {
free(c);
printf("'c' allocated\n");
} else {
free(b);
printf("'c' not allocated\n");
}
return 0;
}
Reading the man page is key here, but the TLDR is if there isn't enough memory to enlarge at the back end of the previous block, it will get a new block of memory, copy the old data into it, and return the address of the new block. The old address should not be used, and most typical realloc statement looks like this
a = realloc(a, 200000 * sizeof(int));
That way you won't accidentally use the possibly wrong old value.
It can't change the address in the pointer, since it is passed by value, so changing it in the function is only changing the local copy.
EDIT : Per Weather Vane's absolutely correct comment, the safer route would be
void * b = realloc(a, 200000 * sizeof(int));
if ( b ) {
a = b;
} else {
;;; /* error handler here */
}
int *a = malloc(40);
int *b;
b=a;
if( *some conditions* )
free(a);
// I know that 'a' has been allocated this chunk of memory X times
// and free(a) has been called less than X times.
I have no idea of that condition, so don't know whether 'a' has been freed or not! So now how would I be sure if 'b' i.e. 'a' has been freed or not.
If you want to make sure that subsequent calls of free on a pointer to dynamically allocated memory will not do any harm, you should assign NULL to that pointer. Because (emphasis added):
The free() function frees the memory space pointed to by ptr, which must have been returned by a previous call to malloc(), calloc() or realloc(). Otherwise, or if free(ptr) has already been called before, undefined behavior occurs. If ptr is NULL, no operation is performed.
If you want to make sure that pointer b will always refer to the same object the other pointer a points at, you could turn b into a pointer to a instead (and dereference it each time you need to use it):
#include <stdio.h>
#include <stdlib.h>
int main() {
/* dynamically allocate some memory */
int *a = malloc(40);
/* b is a pointer to a pointer to an int */
int **b;
/* make b point to a */
b = &a;
if ( 1 ) {
/* free memory and assign NULL to the pointer */
free(a);
a = NULL;
}
/* nothing bad will happen when we dereference b now */
printf("%p\n", *b);
/* nothing bad will happen when we free the memory region
where the pointer b points to points to */
free(*b);
}
Another thing on memory leaks. There will be no memory leaked when you double-free the memory. In that case you will stumble into undefined behavior, in which case anything could happen. Simply because you shall not access memory regions that are not your own (anymore) (c.f., this great post).
Instead, you will leak memory when you loose the reference to a block of dynamically allocated memory. For example:
/* allocate some memory */
int *a = malloc(40);
/* reassign a without free-ing the memory before : you now have leaked memory */
a = malloc(40);
The best option is not having two pointers, pointing to the same place, which are freed independently.
But if that's really what you need, then you need a reference count.
The following code implements a very simple reference count mechanism.
When you assign a second pointer to your data, you should use clone_x to increment the reference count.
Each time you free, use free_x, and it will free just once.
Note that this code isn't multithread-safe. If your code is multi-threaded, you need atomic operations, and you need to be very careful with how you use them.
struct x {
int refcount;
int payload;
};
struct x *create_x(int payload) {
struct x *newx = malloc(sizeof(*newx));
if (!newx) return NULL;
newx->payload = payload;
newx->refcount = 1;
return newx;
}
void clone_x(struct x *myx) {
myx->refcount++;
}
void free_x(struct x *oldx) {
oldx->refcount--;
if (oldx->refcount == 0) {
free(oldx);
}
}
You can't. When free(a) is called it is no longer safe to access that memory.
Even if you malloc() new memory and assign the result to a, that memory could be anywhere.
What you're trying to do will not work.
every allocated memory block should have an 'owner', a or b, if a is the owner, pointer b should not release that block, vice versa.