using calloc vs malloc for dynamic array of struct - c

I've read that the difference between calloc and malloc is that calloc initializes the memory to the default value of the type declared.
For struct, what is the default value?
Is there a difference between using calloc and malloc for dynamic array of struct?
Would the members of the struct also be initialized?

calloc() will initialize the entire allocated memory range to zero. It has nothing to do with what type you are casting to.
malloc() leaves the contents of the memory in an unspecified state.

The calloc function does not initialize memory to the default value for a given type, and in fact it can't because it knows nothing regarding the type that the memory will be used for.
What it does do is set the memory to all bits 0. On most implementations you're likely to come across, this means that integer and floating point types will have the value 0 and that pointer types will be NULL. With regard to structs and/or arrays, this would apply to any members, and additionally any padding within a struct would also have all bits set to 0.

Related

malloc function memory management

malloc() function forms a single block of memory (say 20 bytes typecasted to int), so how it can be used as an array of int blocks like as calloc() function? Shouldn't it be used to store just one int value in whole 20 bytes (20*8 bits)?
(say 20 bytes typecasted to int)
No, the returned memory is given as a pointer to void, an incomplete type.
We assign the returned pointer to a variable of pointer to some type, and we can use that variable to access the memory.
Quoting C11, chapter §7.22.3, Memory management functions
[....] 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 pointer returned points to the start (lowest byte address) of the
allocated space. [....]
Since the allocated memory is contiguous, pointer arithmetic works, just as in case of arrays, since in arrays also, elements are placed in contiguous memory.
One point to clarify, a pointer is not an array.
There's an abstract concept in C formally known as effective type, meaning the actual type of the data stored in memory. This is something the compiler keeps track of internally.
Most objects in C have such an effective type at the point when the variable is declared, for example if we type int a; then the effective type of what's stored in a is int.
Meaning it is legal to do evil things like this:
int a;
double* d = (double*)&a;
*(int*)d = 1;
This works because the effective type of the actual memory remains an int, even though we pointed at it with a wildly incompatible type. As long as we access it with the same type as the effective type, all is well. If we access the data using the wrong type, very bad things will happen, such as program crashes or dormant bugs.
But when we call malloc family of functions, we only tell them to reserve n number of bytes, with no type specified. This memory is guaranteed to be allocated in adjacent memory cells, but nothing else. The only difference between malloc and calloc is that the latter sets all values in this raw memory to zero. Neither function knows anything about types or arrays.
The returned chunk of raw memory has no effective type. Not until the point when we access it, then it gets the effective type which corresponds to the type used for the access.
So just as in the previous example, it doesn't matter which type of pointer we set to point at the data. It doesn't matter if we write int* i = malloc(n); or bananas_t* b = malloc(n);, because the pointed-at memory does not yet have a type. It does not get one until at the point where we access it for the first time.
There is nothing special about memory returned from malloc compared to memory returned from calloc, other that the fact that the bytes of the memory block returned by calloc are initialized to 0. Memory returned by malloc does not have to be used for a single object but may also be used for an array.
This means that the following are equivalent:
int *p1 = malloc(3 * sizeof(int));
p1[0] = 1;
p1[2] = 2;
p1[3] = 3;
...
int *p2 = calloc(3, sizeof(int));
p2[0] = 1;
p2[2] = 2;
p2[3] = 3;
Both will return 3 * sizeof(int) bytes of memory which can be used as an array of int of size 3.
What malloc returns back to you is just a pointer to the starting memory address where the contiguous block of memory was allocated.
The size of the contiguous block of memory that you allocated using malloc depends on the argument you passed into malloc function. http://www.cplusplus.com/reference/cstdlib/malloc/
If you want to store int variable then you will do it by defining the pointer type you use to be of an int type.
example:
int p*; //pointer of type integer
size_t size = 20;
p = (int *) malloc(size); //returns to pointer p the memory address
after this, using the pointer p the programmer can access int (4 byte precision) values.
calloc only difference against malloc is that calloc initiallizes all values at this memory block to zero.

The initialization of the dynamically allocated memory in C [duplicate]

This question already has answers here:
Is malloc() initializing allocated array to zero?
(9 answers)
Closed 4 years ago.
I am still confused with the two functions malloc() and calloc()
As we know calloc() initialize the memory it allocates while malloc() doesn't.
But when I tried the following code, the result seemed unexpected.
typedef struct{
int *val;
}Node;
int main()
{
Node *q=(Node*)malloc(sizeof(Node));
if(q->val==NULL) printf("malloc initialized memory\n");
Node *p=(Node*)calloc(1,sizeof(Node));
if(p->val==NULL) printf("calloc initialized memory\n");
}
The variables 'val' of val of p and q are both NULL. Isn't q->val uninitialized?
Can anyone explain it to me? Thanks!
The malloc function does not initialize the memory it allocates. The contents will be indeterminate (and might seem "random" or "garbage").
If you want to zero-initialize the memory (which means that all pointers are NULL) then use calloc, or explicitly initialize the data.
Also note that in C you should not cast the return of malloc (and siblings).
When a variable is uninitialized, formally it means that its value is indeterminate. It could be any value, and 0 is just as random as any other value. Just because you read 0 doesn't necessarily mean the variable was initialized.
You're actually invoking undefined behavior by attempting to read q->val because 1) it was not initialized and 2) its address was never taken. Had its address been taken first you would not have undefined behavior unless the indeterminate value was a trap representation.
The memory chunk returned via malloc(), contains indeterminate value. Attempt to use that value may incur unspecified result, as nothing about the value can be guranteed.
Quoting C11, chapter 7.22.3.4/P2
The malloc function allocates space for an object whose size is specified by size and whose value is indeterminate.

C - Dynamic allocation of a struct with non dynamics elements

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.

Is this explicit heap or stack dynamic?

Given the following code snippet in C:
int* x;
x = (int *) malloc(40);
We know that this is an explicit heap dynamic allocation.
If I change the code to this though:
int* x = (int *) malloc(40);
is it still an explicit heap dynamic? My friend thinks it's a stack dynamic, but I think its an explicit heap dynamic because we're allocating memory from the heap.
Explicit heap dynamic is defined as variables that are allocated and deallocated by explicit run-time instructions written by the programmer. Wouldn't that imply that any malloc/calloc call would be explicit heap?
Edit: I spoke to my professor and she clarified some stuff for me.
When we declare something like
char * str = (char *) malloc(15);
We say that str is of data type char pointer, and has a stack dynamic storage binding. However, when we are referring to the object referenced by str, we say that it is explicit heap dynamic.
First off, if you are going to store the results of malloc in a variable, then declare it properly as a pointer, not an int.
The problem with storing the malloc results in an int, is that you could possibly truncate the pointer and blow up when you dereference it later. For instance if you ran that expression on a 64 bit system, the malloc would come back with a 8 byte pointer. But since you are assigning it to a 4 byte int, it gets truncated. Not good.
Your code should be like this:
int* x = (int*)malloc(bla);
Anyways, the int pointer x itself is stored on the stack. But don't get the two confused. X itself is a pointer on the stack, but it points to memory allocated on the heap.
Note:
32 bit applications (usually) have 4 byte pointers.
64 bit applications (usually) have 8 byte pointers.
Yes, malloc allocates requested memory on the heap. Heap memory is used for dynamic data structures that grow and shrink.
From standard 6.3.2.3
Any pointer type may be converted to an integer type. Except as previously specified, the result is implementation-defined. If the result cannot be represented in the integer type, the behavior is undefined. The result need not be in the range of values of any integer type.
This claims why the type of the pointer should be int*. Also the casting is not needed - void* to int* conversion will be implicitly done over here.
Also why do you think declaring a variable with initializer or without it would affect the storage duration of the memory allocated by *alloc and it's friend functions. It is not.
Interesting thing x has automatic storage duration (usually this is realized using stack) but the memory it contains (yes type of x would be int*) - it will be of allocated storage duration. The thing is heap/stack are not something specified or mentioned by C standard. Most implementations usually realize allocated storage duration using heap.

Calloc with structure with pointers in C

I know that calloc request memory to be used, writes 0 on all the bits and then returns a pointer to it.
My question is: if I use calloc with a structure that contains pointers, will those pointers have the NULL value or do I have to set them to point to NULL?
struct a{
char * name;
void * p;
}* A;
So basically, will name and p point to NULL after I've used calloc with struct a?
Thanks!
Somehow you've gotten a lot of incorrect answers. C does not require the representation of null pointers to be all-zero-bits. Many people mistakenly think it does, since an integer constant expression with value 0, converted to a pointer, becomes a null pointer.
With that said, on all real-world systems, null pointers are all-zero-bits, and calloc is a perfectly reasonable way to get a null-pointer-initialized pointer array in the real world.
R.'s answer is good, but I'd like to add the standard quotes to support this, and show a way to 0 initialize your struct that does, in fact, yield NULL pointers.
From N1548 (C11 draft)
7.22.3.2 The calloc function allocates space for an array of nmemb objects, each of whose size
is size. The space is initialized to all bits zero.[289]
The footnote then says (emphasis added):
Note that this need not be the same as the representation of floating-point zero or a null pointer constant.
While a null pointer is usually represented as all 0 bits, this representation is not guaranteed. To answer your question directly, no you cannot rely on the calloc()'d struct's pointers to be NULL.
If you want to set all contained pointers of a dynamically allocated struct to NULL you can use the following:
struct a *s = malloc(sizeof *s);
*s = (struct a){0};
C11:
6.7.9.21
If there are fewer initializers in a brace-enclosed list than there are elements or members
of an aggregate, [...] the remainder of the aggregate shall be
initialized implicitly the same as objects that have static storage duration
and
6.7.9.10
... If an object that has static or thread storage duration is not initialized
explicitly, then:
— if it has pointer type, it is initialized to a null pointer;
C requires you to have at least one element inside the braces, which is why I use {0} instead of {}. The rest of the elements are initialized according to the above rules, which results in null pointers. As far as I can tell, the rules for this are the same in C11 and C99.
The ISO C standard for calloc requires it to initialize everything to 0. That means that if you end up veiwing memory allocated by calloc as pointers, it will indeed initially contain NULL (0) pointers.

Resources