Is it safe to malloc on an allocated pointer in C? - c

I'm working on a C library and am trying to be very cautious about memory management. I have a function which allocates memory for a pointer, and am trying to cover the case in which the pointer is already allocated. I am wondering if I need to free the pointer before allocating over it.
char *x = (char *) malloc(12);
// ...
free(x);
x = (char *) malloc(12);
I'm unsure if the free(x) is necessary.

There is no such thing as an allocated pointer.
char *x = (char *) malloc(12); declares a pointer x. Then it allocates 12 bytes of memory and makes x point to the 12 bytes of memory.
free(x); frees the 12 bytes of memory. x still points to the 12 bytes of memory which are now freed.
x = (char *) malloc(12); allocates another 12 bytes of memory and makes x point to the new 12 bytes of memory.
If you removed free(x); then you would be allocating 2 lots of 12 bytes of memory, and not freeing the first lot. Whether that is a memory leak or not depends on how your program is supposed to work - it's only a memory leak if you aren't still using the memory for something.

Yes the free(x) is necessary. If you remove that you will definitely leak memory when you next malloc(12). Now if the sizes are really identical, then I question whether you really need that second malloc. If the sizes differ, you could use realloc() and remove the free.

It is safe, that's to say: you are not incurring in any undefined behaviour. But you are leaking memory, in case you have not saved the address given by the first malloc(), as it should be free()d at some point later.
Not doing the free() is not dangerous, but you cannot recover from that state, as you lost the reference to the memory where that chunk of memory was, so you cannot return it later (it is required by free())
If you don't control to return the memory you are given, and your program does this kind of behaviour, you can finally eat up all the memory available to your process, and this can impact your whole system.

Related

Initialization of malloc & calloc

Why does malloc always initialize with garbage values and calloc always intialize with 0? Any reason behind it?
Why can't we use realloc instead of malloc for dynamic memory allocation?
After reallocating memory dynamically, what are initial values of it?
Code:
int *ptr;
ptr = (int *) realloc(ptr,50);
printf("%d",*ptr);
malloc is made to just allocate memory of the specified size. calloc does the same (with different parameters), but is also designed to zero initialize the memory. It is just how they are designed.
You can use realloc for dynamic reallocation, but it is used to reallocate, which in your example it is not. realloc can only be used on memory already initialized with malloc, calloc, or realloc, or if the pointer is NULL then it is equivalent to malloc
Why does Malloc always initialize with Garbage values & Calloc always intialize with 0?
This behaviour is defined by the C standard.
In fact malloc() does not initialise the memory allocated at all. This mostly is for performance reasons. Do not read it, before having written to it yourself, to not provoke UB.
calloc() is specified to initialise the memory allocated to all 0s.
why can't we use realloc instead of malloc for dynamic memeory allocation.
You can. Just pass NULL as 1st parameter.
Your example adjusted:
int *ptr = NULL;
ptr = realloc(ptr, 50);
*ptr = 42;
printf("%d\n", *ptr);
prints:
42

Reassigning to a pointer variable after freeing it [duplicate]

This question already has answers here:
Reusing freed pointers in C
(4 answers)
Closed 5 years ago.
Is this legal to do? Can you assign ptr to something after it has been freed?
int * ptr = (int*) malloc(sizeof(int));
free(ptr);
ptr = (int *) malloc(sizeof(int));
You aren't reassigning the pointer after freeing it, you're just reusing the ptr variable. This is perfectly fine.
First of all, as I mentioned in the comments, please see this discussion on why not to cast the return value of malloc() and family in C..
That said, yes, the (re)-assignment is fine here.
Actually, the question wording
Can you assign ptr to something after it has been freed?
should read
Can you assign ptr with something after it has been freed?
Guess what, the assignment without free-ing is also legal as per C, but it will create a memory leak as a side effect as the variable ptr was holding the return value of a memory allocator function and you need to free the memory once you're done using it. If, you re-assign the pointer without keeping a copy of the pointer, you'll lose the access to the memory allocated by allocator function and will have no ways to free() it.
In case the pointer was holding an address of statically allocated variable, you don't get to (nned to) free it and direct re-assignment is perfectly fine. think of this below snippet.
int x = 5, y = 10;
int * p = &x;
//do something with p
p = &y; //this is fine, just a re-assignment.
Yes. it is a valid in C language.
Related stack overflow question for more information: Reusing freed pointers in C
According to cwe.mitre.org:
In this scenario, the memory in question is allocated to another
pointer validly at some point after it has been freed. The original
pointer to the freed memory is used again and points to somewhere
within the new allocation. As the data is changed, it corrupts the
validly used memory; this induces undefined behavior in the process.
Can you assign ptr to something after it has been freed?
int * ptr = (int*) malloc(sizeof(int)); /* line 1 */
free(ptr); /* line 2 */
ptr = (int *) malloc(sizeof(int)); /* line 3 */
Taking your question as:
"Is it legal to assign the address of freshly, dynamically allocated memory to a pointer (line 3), after the memory this pointer pointed to from a previous dynamical allocation (line 1) had been freed (line2)?"
Then this answer is yes.
Running line 3 would also be valid without having run line 2. Still, if not calling free() (line 2), the value assigned to ptr (line 1) is overwritten (line 3), and with this the possibility to call free() on ptr's initial value is lost, which in turn leaves the program with leaking exactly this memory allocated initially.
Is this legal to do? Can you assign ptr to something after it has been freed?
Yes, this is legal. ptr can be reassigned as many times as you want. Freeing that pointer is not necessary for reassigning it, for example
int * ptr = malloc(sizeof(int));
int *temp_ptr = ptr; // temp_ptr is pointing to the location ptr is pointing
ptr = malloc(sizeof(int)); // ptr points to new location.
Note that you should not cast the return value of malloc.
Yes you are assigning new memory on heap and its legal.
I would recommend you use realloc instead.
For the case when realloc() fails, from c11, chapter §7.22.3.5,
The realloc function returns ... a null pointer if the new object
could not be allocated.
and
[....] If memory for the new object cannot be allocated, the old
object is not deallocated and its value is unchanged.
The proper way of using realloc will be
ptr_new = realloc(ptr, sizeof(int)*2);
if (ptr_new == NULL)
{
free(ptr);
}
Also please read why should i not cast return value of malloc.
Yes. It is perfectly legal. ptr is a standalone variable that continues to exist regardless of its contents. Nothing happens to the memory location where ptr is stored. There is nothing to prevent you from assigning you any value to it. The correctness of the memory allocation ( malloc / realloc etc) is a different story, but there is nothing wrong with reusing a variable (a memory location) to store the address of a memory location.
When you declare a pointer it will be allocated for it a memory location. That location can be reassigned.
If you reassign it after having assigned it a value with a malloc() call and before to free() it, this is a memory leak. After free() you can reassign it and no leak will happen, do not forget to free() it again.
In fact, the operating systems that are useful programs that never finish will reassign all the time some fixed pointers toward processes, free them when the process finishes, etc.
The programming in which assignments are not allowed is called functional programming.

Allocating and reallocating a struct and its elements

I have a few questions about allocating memory to structs and their members.
Suppose I have a struct like this:
struct _MyStruct
{
char *a;
}
typdef struct _MyStruct MyStruct;
I want 'a' to be a dynamic string and I want to allocate memory to it. Should I allocate memory to MyStruct too in this case? Example:
MyStruct *myStr = malloc(sizeof(MyStruct)); //necessary?
MyStruct *myStrCopy = myStr;
myStrCopy->a=malloc(sizeof(char));
//checking for null//
Now suppose I allocated an X amount of memory to the struct (myStr). Now, when I allocate memory to 'a', is the memory allocated within the memory allocated to myStr, or does it get a new block of memory?
Can I allocate more memory to 'a' than I allocated to myStr?
Suppose I want to enlarge 'a' with realloc(). Should I enlarge myStr first? If I do, then by what amount of memory (sizeof(myStr)*size_of_my_string)?
I want 'a' to be a dynamic string and I want to allocate memory to it. Should I allocate memory to MyStruct too in this case?
Well, your MyStruct always needs to exist, but there are several ways to do this and you should go for the simplest one that fits your use case.
Basic approach:
MyStruct myStr;
myStr.a = malloc(N); // "N chars please!"
// You can still get a pointer to this object:
foo(&myStr);
// Don't forget to free the `char` buffer later
free(myStr.a);
Dynamic allocation — valid, but not inherently necessary:
MyStruct* myStr = malloc(sizeof(MyStruct));
myStr->a = malloc(N); // "N chars please!"
// It's already a pointer, so:
foo(myStr);
// Don't forget to free the `char` buffer later
free(myStr->a);
// And then the struct
free(myStr);
Now suppose I allocated an X amount of memory to the struct (myStr). Now, when I allocate memory to 'a', is the memory allocated within the memory allocated to myStr, or does it get a new block of memory?
It's a new block.
Each block of dynamically allocated memory is entirely separate. When you made the member variable a a pointer, you ensured that although a lives within the struct, the thing it points to does not (unless you make it point to itself, lol).
myStr (or *myStr): your malloc'd memory:
0 32 0 8 16 24 32 40 ...
+----------+ +------------------------------+
| char* a——|———————————————————————→| text or whatever here |
+----------+ +------------------------------+
(somewhere in memory) (somewhere else in memory)
The above diagram is valid no matter which way you constructed myStr.
Can I allocate more memory to 'a' than I allocated to myStr?
Yeah, whatever you want. It's separate. You have indirection.
Suppose I want to enlarge 'a' with realloc(). Should I enlarge myStr first? If I do, then by what amount of memory (sizeof(myStr)*size_of_my_string)?
No.
Just for clarification:
myStr and
a are just pointer to some memory location. This does not mean they are sharing the same memory location.
So allocating either myStr or a is not growing the variable it self.
It requests new memory somewhere in the virtual memory space of the process and stores the address in the corresponding pointer..
So to answer you question: Yes you can allocate a memory for a which is larger than myStr.
Update for better illustration:
0x000 | 0x004 | 0x008 | 0x0012 | 0x0016
^ ^
| |
myStr a
So myStr could be located in memory somewhere completly different compared to a.
Not needed to allocate for structure.Just for char* is enough. Say
MyStruct str;
str.a = malloc( sizeof(char)*10);
str will be in stack. Memory pointed by 'a' will be in heap. So when str goes out of scope, the object will be destructed. But not the dynamically allocated one which is pointed by 'a'. We have delete it manually.
The size of structure will be same won't vary with the size of dynamic memory pointed by 'a'.
Just reallocate the memory pointed by 'a'.
str.a = realloc(a, sizeof(char)*20);
First case
MyStruct *myStr = malloc(sizeof(MyStruct)); //necessary?
yes, very much. Without the allocation to myStr first, trying to dereference myStr (to reach a) is undefined behaviour.. Also, FWIW,
myStrCopy->a=malloc(sizeof(char));
allocates only memory for only one char, be sure that is what you actually want. If you really want that, in that case, you can rewrite that as
myStrCopy->a=malloc(1);
as sizeof(char) is guranteed to be 1 in C.
Every allocation through malloc() and family gives you a new memory, if successful.
You can, and you should. There is no relation actually. They are separate variables and need seperate memory allocation.
No, only realloc() on a should suffice.

size of memory allocated by malloc

I am assigning a new memory chunk to a pointer, but apparently the size of the chunk is not the one which I pass as a parameter to malloc
char *q="tre";
printf("q in main %zu\n", sizeof(q));
q = (char*)malloc(6);
printf("q in main %zu\n", sizeof(q));
Outputs
8
8
The pointer however does point to a new memory chunk.
How is this possible?
sizeof returns size of pointer, in your case it is (char*), it will not give the memory allocated by the malloc. Keep the memory size in separate variable for later use.
char *q;
printf("%zu\n", sizeof(q));
sizeof(q) refers to the size of the pointer, not the amount of memory it points to.
What you are obtaining is the size of the variable q as a pointer type. In general all pointers will have the same size in your program.
Since 8 bytes are 64 bits, it seems you are doing 64-bit applications. :)
sizeof(q) returns the size of the pointer q which will on a 64 bit machine be 8 bytes, not the size of the memory block allocated at that pointer. sizeof is a compile time not a runtime operation.
I'm not clear what you want to do here, but if you want to allocate enough memory for a string at location s, then you want to malloc(strlen(s)+1) (+1 for the terminating NULL).
Perhaps you want to get the size of malloc()ed block. There is not a portable way to do this to my knowledge, but malloc_usable_size nearly does it on glibc. From the man page:
malloc_usable_size() returns the number of bytes available in the dynamically allocated buffer ptr, which may be greater than the requested size (but is guaranteed to be at least as large, if the request was successful). Typically, you should store the requested allocation size rather than use this function.
Note the last sentence.

realloc in C — exact behaviour and uses

Reading some literature, I was able to grasp that realloc takes in a void pointer and a size variable and re-allocates the memory of the block the void pointer points to.
What will happen if realloc is called on an integer pointer (int *)
with a size of character? And vice versa.
What can be a possible application of this? (An example would definitely help.)
The realloc() function is the all-in-one memory management system.
If called with a null pointer and a non-zero size, it allocates memory.
If called with a valid pointer and a zero size, it frees memory.
If called with a valid pointer and a non-zero size, it changes the size of the allocated memory.
If you call realloc() with an invalid pointer — one which was not obtained from malloc(), calloc() or realloc() — then you get undefined behaviour.
You could pass realloc() an integer pointer to an allocated space of sizeof(char) bytes (1 byte), but you'd be in danger of invoking undefined behaviour. The problem is not with realloc(); it is with the code that was given an unusable integer pointer. Since only 1 byte was allocated but sizeof(int) is greater than 1 (on essentially all systems; there could be exceptions, but not for someone asking this question), there is no safe way to use that pointer except by passing it to free() or realloc().
Given:
int *pointer = malloc(sizeof(char));
you cannot do *pointer = 0; because there isn't enough space allocated (formally) for it to write to. You cannot do int x = *pointer; because there isn't enough space allocated (formally) for it to read from. The word 'formally' is there because in practice, the memory allocators allocate a minimum size chunk, which is often 8 or 16 bytes, so there actually is space after the one byte. However, your are stepping outside the bounds of what the standard guarantees, and it is possible to conceive of memory allocators that would hand you exactly one byte. So, don't risk it. An integer pointer to a single byte of allocated memory is unusable except as an argument to the memory allocation functions.
The first argument to realloc() is a void *. Since you're going to have a prototype in scope (#include <stdlib.h>), the compiler will convert the int * to a void * (if there's anything to do for such a cast), and as long as the space pointed at was allocated, everything will be fine; realloc() will change the allocation size, possibly returning the same pointer or possibly returning a different pointer, or it will release the space if the new size is zero bytes.
There is a vitally important requirement to non-NULL pointers that you pass to realloc: they must themselves come from a call to malloc, calloc or realloc, otherwise the behavior is undefined.
If you allocate a chunk of memory sufficient to store an int and then realloc for a char, you will always get back the same pointer, because sizeof(char) is less than or equal to the sizeof(int):
int* intPtr = malloc(sizeof(int));
int* otherPtr = realloc(intPtr, sizeof(char));
// intPtr == otherPtr
If you try it the other way around, you will almost certainly get back the same pointer as well, because memory allocators rarely, if ever, parcel the memory to chunks smaller than sizeof(int). However, the result is implementation-dependent, so theoretically you may get back a different address.
As far as the utility of any of the above exercises goes, it is not useful: realloc has been designed with the intention to help you manage variable-sized arrays, simplifying the code for growing the size of such arrays, and potentially reducing the number of allocations and copying. I do not see a reason for realloc-ing a scalar.
The type of the first parameter of realloc is void *, as you said yourself. So the function argument that you pass is converted to a void pointer, which is an implicit and safe conversion.
It's the same as if you called a function with a long int parameter with an int argument, essentially.
Realloc takes the size in bytes. If you do
int* a= malloc(sizeof(int));
and then
a=realloc(a,1);
of course a will now not be big enough for an int type and writing an int in it will give you odd behavior.
As stated by dasblinkenlight, realloc doesn't make sense for a scalar.
In your example:
int * a = malloc(sizeof(int));
int * b = realloc(a,sizeof(char));
Would result in a == b, simply because sizeof(char) < sizeof(int) and there is no reason for moving the data to a new location.
The difference is, that after the realloc you are writing your int to unallocated space, as you decreased the allocated space using realloc. Here this is only of theoretical relevance. Because of alignment it is very unlikely, that the os is reusing the freed memory. But you shouldn't rely on that. This is undefined behavior.
It could become relevant, if you resize the space of a long int to an int. This depends on your architecture.
Writing to unallocated space is like laying a time bomb and not knowing when it will explode. You should only read from / write to allocated space.

Resources