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);
Related
Building on what I learned here: Manipulating dynamic array through functions in C.
void test(int data[])
{
data[0] = 1;
}
int main(void)
{
int *data = malloc(4 * sizeof *data);
test(data);
return 0;
}
This works fine. However, I am also trying to using realloc in a function.
void increase(int data[])
{
data = realloc(data, 5 * sizeof *data);
}
This complies but the program crashes when run.
Question
How should I be using realloc in a function?
I understand that I should assign the result of realloc to a variable and check if it is NULL first. This is just a simplified example.
You want to modify the value of an int* (your array) so need to pass a pointer to it into your increase function:
void increase(int** data)
{
*data = realloc(*data, 5 * sizeof int);
}
Calling code would then look like:
int *data = malloc(4 * sizeof *data);
/* do stuff with data */
increase(&data);
/* more stuff */
free(data);
Keep in mind the difference between a pointer and an array.
An array is a chuck of memory in the stack, and that's all.If you have an array:
int arr[100];
Then arr is an address of memory, but also &arr is an adress of memory, and that address of memory is constant, not stored in any location.So you cannot say arr=NULL, since arr is not a variable that points to something.It's just a symbolic address: the address of where the array starts.Instead a pointer has it's own memory and can point to memory addresses.
It's enough that you change int[] to int*.
Also, variables are passed by copy so you need to pass an int** to the function.
About how using realloc, all the didactic examples include this:
Use realloc;
Check if it's NULL.In this case use perror and exit the program;
If it's not NULL use the memory allocated;
Free the memory when you don't need it anymore.
So that would be a nice example:
int* chuck= (int*) realloc (NULL, 10*sizeof(int)); // Acts like malloc,
// casting is optional but I'd suggest it for readability
assert(chuck);
for(unsigned int i=0; i<10; i++)
{
chunk[i]=i*10;
printf("%d",chunk[i]);
}
free(chunk);
Both code are very problematic, if you use the same pointer to send and receive from realloc, if it fails, you will lose your pointer to free it later.
you should do some thing like this :
{
...
...
more = realloc(area , size);
if( more == NULL )
free(area);
else
area=more;
...
...
}
I am implementing a function to safely realloc a structure in order not to lost the information if any allocation error occurs, something like this:
int foo (someStruct_t *ptr, int size)
{
someStruct_t *tmp_ptr;
tmp_ptr = realloc(ptr, size);
if (tmp_ptr == NULL)
return -1;
ptr = tmp_ptr;
return 0;
}
My doubt resides in the following: Am I not duplicating the allocated memory for the structure everytime I run this function? In my line of thought I should free one of the pointers before exiting, correct?
The primary and major problem here is, after a call to foo(), in the caller, the passed argument for ptr will not be changed, as it itself is passed by value.
You need to pass a pointer to the pointer which you want to be reallocated, in case you don't want to return the new pointer.
That said, there is no "duplication" of memory here.
From realloc() point of view
realloc(), if successful, returns the pointer to the new memory and handles the job of de-allocating the older one. You don't need to worry about any duplication or memory leaks.
Quoting C11, chapter ยง7.22.3.5 (emphasis mine)
The realloc function deallocates the old object pointed to by ptr and returns a
pointer to a new object that has the size specified by size. [....]
[....] If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
From the assignment point of view
A statement like ptr = tmp_ptr; does not duplicate the memory or memory contents the pointer points to, it is just having two copies of the same pointer. For example, You can pass either of them to free().
So, bottom line, to answer the "question" in the question,
In my line of thought I should free one of the pointers before exiting, correct?
No, you should not. You need to have the newly allocated pointer to be useful in the caller, free()-in it inside the called functions makes the whole function pointless. You should free the pointer from the caller, though.
int foo (someStruct_t **ptr, int size)
{
someStruct_t *tmp_ptr;
tmp_ptr = realloc(*ptr, size);
if (tmp_ptr == NULL)
return -1;
*ptr = tmp_ptr;
return 0;
}
the posted code contains several problems:
cannot change where a caller's pointer points without the address of that pointer, so use ** in the parameter list and call the function using: foo( &ptr, size);
each reference to the callers' pointer must now be dereferenced via a *
usually the size refers to the number entries room to be allocated, so size needs to be multiplied by sizeof( someStruct_t )
note the use of size_t for the size parameter because realloc() is expecting the second parameter to have the type: size_t
and now the proposed code:
#include <stdlib.h> // realloc()
int foo (someStruct_t **ptr, size_t size)
{
someStruct_t *tmp_ptr;
tmp_ptr = realloc( *ptr, sizeof( someStruct_t) * size );
if (tmp_ptr == NULL)
return -1;
*ptr = tmp_ptr;
return 0;
} // end function: foo
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.