C - Dynamic allocation of a struct with non dynamics elements - c

I was wondering where a struct would be allocated in memory if I have something like this.
typedef struct {
int c;
} A;
A * a = (A)* malloc(sizeof(A));
a -> c = 2;
C would be allocated in the heap area, is that right?
Moreover, if I free the memory with
free(a);
What happens to the memory area occupied by C?

A * a = (A)* malloc(sizeof(A));
This line is incorrect, if you want to make an explicit cast, the syntax is (A*), not (A)*.
Anyway, yes, malloc allocates memory on the heap (in general and on non exotic system). What happens after depends on the OS and the implementation of the libc you use. Most often however, the memory freed is kept in a list for future use by malloc.

First of all you need to allocate the memory like A * a = (A*) malloc(sizeof(A));. In C when you allocate memory to a struct dynamically you need to provide total size of that struct and the return type conversion from void* to your data type. So your malloc call will allocate that much of memory and returns a void pointer to the first byte of that block of memory location.
So do not confuse that declaring variable inside a struct will be allocated from stack. Please see below:-
int c;// c is a automatic variable and memory will be allocated from stack
typedef struct {
int c;// c is not a automatic variable it is simply a data member of `struct A`
} A;
So in the second case memory will be allocated to c only when malloc will be called at run time that is dynamically and from heap. So your free call will simply release that memory at run time.
But
typedef struct {
int c;// c is not a automatic variable it is simply a data member of `struct A`
} A;
A a;// Here 'a' is a automatic variable so 'int c' is also become automatic here
//and memory for the entire struct A will be allocated from stack and
//you no need to use `free` here
Hope this is help.

A * a = (A)* malloc(sizeof(A));
Where a struct would be allocated in memory?
In C, the library function malloc allocate a block of memory on the heap. The program accesses this block of memory via a pointer that malloc returns. The memory is given by the operating system. If memory is not available NULL pointer is returned.
There is no need for casting of malloc in C. Your code has a typo, if anything it should be (A *).
What happens to the memory area occupied by C?
When the memory is no longer needed, the pointer pointing to the allocated memory should be passed to free which deallocates the memory so that it can be used again. For free(NULL); the function does nothing.
C11 standard (ISO/IEC 9899:2011):
7.22.3.3 The free function
Synopsis
#include <stdlib.h>
void free(void *ptr);
Description
The free function causes the space pointed to by ptr to be
deallocated, that is, made available for further allocation. If ptr is
a null pointer, no action occurs. Otherwise, if the argument does not
match a pointer earlier returned by a memory management function, or
if the space has been deallocated by a call to free or realloc, the
behavior is undefined.

Fistly, C is a case-sensitive language.
int c is not the same as int C, so you might want to edit that in your question.
Now, lets answer your questions:
C would be allocated in the heap area, is that right?
Yes it is allocated from heap, subject to availability.
If you forget to release memory that was allocated, you will exhaust it.
Lets see what C11 standard says, C11 - Section 7.22.3 states,
The pointer returned if the allocation succeeds is suitably aligned so that it may be assigned to a pointer to any type of object with a fundamental alignment requirement and then used to access such an object or an array of such objects in the space allocated (until the space is explicitly deallocated). The lifetime of an allocated object extends from the allocation until the deallocation. Each such allocation shall yield a pointer to an object disjoint from any other object. The pointer returned points to the start (lowest byte address) of the allocated space. If the space cannot be allocated, a null pointer is returned. If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object.
Thats should suffice to justify why explicit typecasting in statement
A * a = (A)* malloc(sizeof(A));
is not required. So it should be
A * a = malloc(sizeof(A));
followed by test if a is NULL, if it is NULL, you shouldn't continue with further access.
What happens to the memory area occupied by C?
Again, referring to C11 standard, C11 - Section 7.22.3.3 which states,
The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined.
a in your code is equivalent to ptr above. Once freed, you can consider that the memory is returned to heap-pool for fresh allocations. There is no memory occupied by c now, and hence an access to c results in Undefined Behavior.
Refer C11 Standard, section J.2 Undefined Behavior:
An object is referred to outside of its lifetime (6.2.4).
The value of a pointer to an object whose lifetime has ended is used (6.2.4).

A * a = (A)* malloc(sizeof(A));
The compiler must be giving an error on this statement and if I am guessing correctly you want to cast the malloc return with (A *) which you should not do [check this].
In C language, a structure is a user-defined datatype which allows us to combine data of different types together and size of a structure variable is
size of all member variables + size of structure padding
So, when you dynamically allocate memory of sizeof(struct name) size, a block of memory of requested size gets allocated in heap and when you pass this pointer to free(), it deallocates that whole memory block.
What happens to the memory area occupied by C?
It is deallocated.
The lifetime of a dynamically allocated object is over when it is deallocated. So, when you do free(a), the life of a and all its data members is over and it is indeterminate now.
Additional:
A point to note here about free() is that it does not change the value of the pointer (passed to it) itself, hence it still points to the same (now invalid) location.
So, when you free a dynamically allocated memory it still points to the same location which is no more valid and accessing such memory is undefined behavior. From C Standard#6.2.4p2
The lifetime of an object is the portion of program execution during which storage is guaranteed to be reserved for it. An object exists, has a constant address,33) and retains its last-stored value throughout its lifetime.34) If an object is referred to outside of its lifetime, the behavior is undefined. The value of a pointer becomes indeterminate when the object it points to (or just past) reaches the end of its lifetime.

Related

Can I realloc() an unallocated pointer?

Normally, realloc() is used to reallocate a previously allocated pointer:
int *DynamicArray = malloc(sizeof(int)*SomeArbitraryValue);
// Some rando code where DynamicArray is used
DynamicArray = realloc(DynamicArray, sizeof(int)*SomeOtherArbitraryValue)
But can realloc() be used to directly allocate memory? As in
int *DynamicArray = realloc(/*...*/);
Can realloc() handle non-preallocated pointers?
Yes, just pass NULL to it's first argument.
The manpage of realloc(3) says ...
The realloc() function changes the size of the memory block pointed to by ptr to size bytes. The contents will be unchanged in the range from the start of the region up to the minimum of the old and new sizes. If the new size is larger than the old size, the added memory will not be initialized. If ptr is NULL, then the call is equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr). Unless ptr is NULL, it must have been returned by an
earlier call to malloc(), calloc(), or realloc(). If the area pointed to was moved, a free(ptr) is done.
As the answer by #ZhangBoyang tells you, yes, assuming one possible interpretation of your question. However the way you've worded your question ("non-preallocated pointers") suggests you may have misunderstanding of some of the concepts involved. malloc does not "allocate pointers". It allocates objects, and pointers are values that point to objects. The lifetime of those objects are not connected to the lifetime of any particular pointer pointing to them.
Passing a pointer to realloc doesn't "do anything to" the pointer. It does something to the object pointed to by it. If the pointer is uninitialized or invalid, the call has undefined behavior and bad things will happen. If the pointer is a null pointer, however, realloc(ptr, n) will behave exactly as malloc(n).

How does realloc() reallocate the memory?

How does realloc() reallocate the memory which was first allocated by malloc()?
I know that you need to use malloc() before you´re able to reallocate the memory, but I don´t understand how that really should work. What if a dynamic-memory object gets decreased in size by realloc()? Is this respective piece of the object just erased after the call to realloc()?
My Question is:
How does the realloc() function reallocate a dynamic-memory object created by malloc()?
Note: I did this Q&A because many beginners seem to be still confused about the issue of reallocating memory using realloc() despite already existing questions here on SO for that topic. They seem to be a little confusing for anyone who is new to the topic and still do not represent the whole behavior of realloc(). Therefore, and because the questions, IMHO, still do not quite fit the answer I´d want to give, I made my own Q&A.
Note: All citations in the following answer are quoted from the actual C standard, ISO/IEC 9899:2018 (C18), section 7.22.3.4.
First, the synopsis for the realloc() function from ISO/IEC 9899:2018, Section 7.22.3:
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
Despite its name, the realloc() function does not "reallocate" anything. realloc() is not modifying an extant object in memory. Instead, it does some sort of "create (new object) & copy the data" routine.
If size is not 0 and ptr either points to an object that was allocated by one of the memory management functions (not just malloc() only) or points to NULL, then realloc() usually creates a new object and copies the data from the old object into the new object.
*I do say usually because you can´t assume that a new object in memory is really allocated. You must always check whether or not it was allocated by checking whether the returned pointer points to NULL.
If the size of the new object is larger than the old object, the bytes of the new object that are beyond the size of the old object have indeterminate values. If the new object is shorter than the old object, the values inside the difference between are thrown away. Every other value remains in the new object as it was in the old one.
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. Any bytes in the new object beyond the size of the old object have indeterminate values.
After that, if:
ptr is not a pointer to NULL and is a pointer earlier returned by a memory management function, and the object this pointer is pointing to has not been deallocated before the call to realloc(),
If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory management function, or if the space has been deallocated by a call to the free or realloc function, the behavior is undefined.
size is not 0,
If size is zero and memory for the new object is not allocated, it is implementation-defined whether the old object is deallocated. If the old object is not deallocated, its value shall be unchanged.
and a new object could really be allocated if realloc() did not return a pointer to NULL,
If size is nonzero and memory for the new object is not allocated, the old object is not deallocated
and really only if all of these premises are fulfilled, realloc() deallocates the memory of the old object and returns a pointer with the address of the new object in memory.
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 realloc() returns a pointer to NULL, no new object is created and the old object remains unchanged at its address in memory.
Optionally, to make the "pseudo-reallocating" behavior almost perfect, it is possible that the new object, after the deallocation of the old object is done (if it happens), is allocated back at the same address in memory where the old object was stored.
The realloc function returns a pointer to the new object (which may have the same value as a pointer to the old object), or a null pointer if the new object has not been allocated.
In this case, there are logically two data copying processes in realloc(), one time into a buffer object and later back to the place of where the original old object was stored. The buffer object is deallocated after the execution of realloc()is completed.
The pointer of ptr which first is used for pointing to the old object should not be used for the returned pointer. If the call statement to realloc() looks like this:
ptr = realloc(ptr,size);
then you usually have a memory leak if the reallocation fails because you just overwrote the pointer to the old memory with a null pointer. If you don't have another pointer that points to it, you've leaked the memory.
Therefore, it is usually better to use a variant on:
void *new_space = realloc(ptr, new_size);
if (new_space == NULL)
{
/* …handle out of memory condition… */
/* ptr is still valid and points to the previously allocated data */
return; /* Or otherwise do not continue to the following code */
}
ptr = new_space;
size = new_size;
Note that according to what I´ve said above, the address may be the same as before the call to realloc().
To make sure that memory management is really happening that way, we can try this experiment:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
size_t length1 = 4;
size_t length2 = 2;
int *ptr1 = malloc(sizeof(*ptr1) * length1);
if(ptr1 == NULL)
{
printf("The object could not be allocated!\n");
return 1;
}
printf("value (not address) of ptr1 before realloc(): %p\n", (void *)ptr1);
ptr1 = realloc(ptr1,length2);
if(ptr1 == NULL)
{
printf("No new object allocated. Old object remains!\n");
return 1;
}
printf("value (not address) of ptr1 after realloc(): %p\n", (void *)ptr1);
free(ptr1);
return 0;
}
At my try it gave the output of:
value (not address) of ptr1 before realloc(): 0x1db4010
value (not address) of ptr1 after realloc(): 0x1db4010
So, the address stored in ptr1 after the use of realloc() is equivalent to before the call of it.
Additional Notes:
realloc() acts as malloc() when ptr is a NULL pointer:
int *ptr = NULL;
size_t length = 4;
ptr = realloc(ptr,sizeof(*ptr) * length);
shall have the same effect as,
int *ptr;
size_t length = 4;
ptr = malloc(sizeof(*ptr) * length);
If ptr is a null pointer, the realloc function behaves like the malloc function for the specified size.
But, in my personal opinion, you should not first allocate dynamic storage by the use of realloc(). I recommend that you always use malloc() or another allocating memory management function instead. It may cause some difficulties to future readers.
You should not use realloc(ptr,0) as substitution for free(ptr) to deallocate the dynamic memory because it is implementation-defined whether the old object is really deallocated or not.
If size is zero and memory for the new object is not allocated, it is implementation-defined whether the old object is deallocated. If the old object is not deallocated, its value shall be unchanged.
Always use free() to deallocate a dynamically allocated object.

C - pointer being freed was not allocated

I am trying to free a pointer that I assigned from a vector allocated with malloc(), when I try to remove the first element(index [0]), it works, when I try to remove the second(index [1]) I receive this error:
malloc: *** error for object 0x100200218: pointer being freed was not allocated
The code:
table->t = malloc (sizeof (entry) * tam);
entry * elem = &table->t[1];
free(elem);
You can only call (or need to) free() on the pointer returned by malloc() and family.
Quoting C11, chapter §7.22.3.3
[...] Otherwise, if
the argument does not match a pointer earlier returned by a memory management
function, or if the space has been deallocated by a call to free or realloc, the
behavior is undefined.
In your case, table->t (or, &table->t[0]) is that pointer, not &table->t[1].
That said, free()-ing table->t frees the whole memory block, you don't need to (you can't, rather) free individually/ partially. See this answer for more info.
It works on the first element because &table->t[0] is equal to table->t. That's because the first element has the same address as the array itself (by definition of the array).
And since the array itself has an address that has been allocated, only that one can be freed.
malloc() works by allocating a single contiguous memory area, whose usable size is the single integer parameter passed by it. It returns a pointer for the allocated area.
You can only free the returned pointer once, and not a subset of it.
Arrays aren't objects in C, they're syntatic sugar to pointer arithmetic, which is probably the main headache of C programming and the area you should carefully study if you're committed to learning C.

Successive pointer allocations; Reallocated or allocated distinct?

If I allocate memory to pointers in a loop successively, does the compiler consider it as a single instance? Concretely:
for (i = 0; i < SOME_VAL; i++)
{
char *p = NULL;
p = malloc(sizeof(char));
SEND_POINTER_ON_NETWORK(p);
}
Will the compiler at every execution create a new instance of p or will it continue allocating memory to p? I am using VS2010.
char *p = NULL;
p = malloc(sizeof(char));
Each call to malloc() within the loop allocates new memory location to the pointer p , if you are trying to extend the already allocated memory to p then use realloc().
The memory management system looks for a free memory slot at the size of the argument in malloc (in this case sizeof(char)). You do not free the memory from one iteration to the next. Therefore, the memory management system 'sees' the memory as occupied and allocates a new memory slot to pointer p.
You have a memory leak in your code.
From ISO/IEC 9899:
(known as c99 standard)
7.20.3.3 The malloc function
Synopsis
1 #include <stdlib.h>
void *malloc(size_t size);
Description
2 The malloc function allocates space for an object whose size is specified by size and
whose value is indeterminate.
Returns
3 The malloc function returns either a null pointer or a pointer to the allocated space.
The behaving you expect would be made by realloc, which is described as follows:
7.20.3.4 The realloc function
Synopsis
1 #include <stdlib.h>
void *realloc(void *ptr, size_t size);
Description
2 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. 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. Any bytes in the new object beyond the size of the old object have
indeterminate values.
3 If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by the
calloc, malloc, or realloc function, or if the space has been deallocated by a call
to the free or realloc function, the behavior is undefined. If memory for the new
object cannot be allocated, the old object is not deallocated and its value is unchanged.
Returns
4 The realloc function returns a pointer to the new object (which may have the same
value as a pointer to the old object), or a null pointer if the new object could not be
allocated.
Also notable is the fact, that MSVC compiler isn't strict conform to the standard in all topics.
But in the both cited cases I know they are conform with it. So it is also valid for your question.

Freeing allocated memory: realloc() vs. free()

so I have a piece of memory allocated with malloc() and changed later with realloc().
At some point in my code I want to empty it, by this I mean essentially give it memory of 0. Something which would intuitively be done with realloc(pointer,0). I have read on here that this is implementation defined and should not be used.
Should I instead use free(), and then do another malloc()?
It depends on what you mean: if you want to empty the memory used, but still have access to that memory, then you use memset(pointer, 0, mem_size);, to re-initialize the said memory to zeroes.
If you no longer need that memory, then you simply call free(pointer);, which'll free the memory, so it can be used elsewhere.
Using realloc(pointer, 0) may work like free on your system, but this is not standard behaviour. realloc(ptr, 0) is not specified by the C99 or C11 standards to be the equivalent of free(ptr).
realloc(pointer, 0) is not equivalent to free(pointer).
The standard (C99, §7.22.3.5):
The realloc function
Synopsis
1
#include <stdlib.h>
void *realloc(void *ptr, size_t size);
Description
2 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. 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. Any bytes in the new object beyond the size of the old object have
indeterminate values.
3 If ptr is a null pointer, the realloc function behaves like the malloc function for the
specified size. Otherwise, if ptr does not match a pointer earlier returned by a memory
management function, or if the space has been deallocated by a call to the free or
realloc function, the behavior is undefined. If memory for the new object cannot be
allocated, the old object is not deallocated and its value is unchanged.
Returns
4
The realloc function returns a pointer to the new object (which may have the same
value as a pointer to the old object), or a null pointer if the new object could not be
allocated.
As you can see, it doesn't specify a special case for realloc calls where the size is 0. Instead, it only states that a NULL pointer is returned on failure to allocate memory, and a pointer in all other cases. A pointer that points to 0 bytes would, then, be a viable option.
To quote a related question:
More intuitively, realloc is "conceptually equivalent" to to malloc+memcpy+free on the other pointer, and malloc-ing a 0-byte chunk of memory returns either NULL either a unique pointer, not to be used for storing anything (you asked for 0 bytes), but still to be freeed. So, no, don't use realloc like that, it may work on some implementations (namely, Linux) but it's certainly not guaranteed.
As another answer on that linked question states, the behaviour of realloc(ptr, 0) is explicitly defined as implementation defined according to the current C11 standard:
If the size of the space requested is zero, the behavior is implementation-defined: either a null pointer is returned, or the behavior is as if the size were some nonzero value, except that the returned pointer shall not be used to access an object
realloc() is used to increase or decrease the memory and not to free the memory.
Check this, and use free() to release the memory (link).
I don't think you mean "empty"; that would mean "set it to some particular value that I consider to be empty" (often all bits zero). You mean free, or de-allocate.
The manual page says:
If ptr is NULL, then the call is equivalent to malloc(size), for all values of size; if size is equal to zero, and ptr is not NULL, then the call is equivalent to free(ptr).
Traditionally you could use realloc(ptr, 0); as a synonym for free(ptr);, just as you can use realloc(NULL, size); as a synonym for malloc(size);. I wouldn't recommend it though, it's a bit confusing and not the way people expect it to be used.
However, nowadays in modern C the definition has changed: now realloc(ptr, 0); will free the old memory, but it's not well-defined what will be done next: it's implementation-defined.
So: don't do this: use free() to de-allocate memory, and let realloc() be used only for changing the size to something non-zero.
Use free() to free, to release dynamically allocated memory.
Although former documentations state that realloc(p, 0) is equivalent to free(p), the lastest POSIX documentation explictly states that this is not the case:
Previous versions explicitly permitted a call to realloc (p, 0) to free the space pointed to by p and return a null pointer. While this behavior could be interpreted as permitted by this version of the standard, the C language committee have indicated that this interpretation is incorrect.
And more over:
Applications should assume that if realloc() returns a null pointer, the space pointed to by p has not been freed.
Use free(pointer); pointer = 0 instead of realloc(pointer, 0).
void* realloc (void* ptr, size_t size);
In C90 :
if size is zero, the memory previously allocated at ptr is deallocated as if a call to free was made, and a null pointer is returned.
In C99:
If size is zero, the return value depends on the particular library implementation: it may either be a null pointer or some other location that shall not be dereferenced.
I would use realloc to give a pointer more or less memory, but not to empty it. To empty the pointer I would use free.

Resources