I want to create dynamic array in the heap using malloc.
int *c = malloc(5 * sizeof(int));
The problem is that it is not initialized by zero and I'd like avoid using calloc as much as I can since I don't know how safe it is.
If I use calloc, is it going to do the same malloc job?
malloc():
malloc() takes one arguement: the amount of bytes to be allocated. The allocated bytes are uninitialized. Hence, their values could be anything from 0-255, or any combination of those numbers. Don't count on anything!
Code Sample:
int *mem = malloc(5 * sizeof(int));
calloc():
calloc() takes two arguements: the amount of elements to allocate memory for and the amount of memory that needs allocated for each element. It initializes each byte to zero.
Code Sample:
int *mem = calloc(5, sizeof(int));
From The C programming Language ~ Brian W. Kernighan and Dennis M. Ritchie:
void *calloc(size_t nobj, size_t size)
calloc returns a pointer to space for an array of nobj objects,
each of size size, or NULL if the request cannot be satisfied.
The space is initialized to zero bytes.
[Emphasis mine]
Alternatively, you can initialize memory with memset()
#include <string.h> // for memset()
//allocate memory
int *mem = malloc(5 * sizeof(int));
//initialize memory to zeros
memset(mem, 0, 5 * sizeof(int));
You can use calloc(), it's safe or else why would it be implemented in the standard library and how? It will be presumably more efficient than malloc() + memset() for large allocations.
You can use memset if you want to avoid using calloc for some reason. you can do it like this:
memset (c, 0, 5 * sizeof(int));
Don't forget to check the return value from malloc.
Related
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
I have a char** which is designed to hold and unknown amount of strings with unknown length
I've initially allocated 10 bytes using
char **array = malloc(10);
and similarly, before adding strings to this array, I allocate
array[num] = malloc(strlen(source)+1)
I've noticed that my program crashes upon adding the 6th element to the array
My question is, how does memory with these arrays work? When I allocated 20 bytes, nothing happened, yet when I allocated 30, it suddenly could hold 10 elements. These were all strings of 2-3 characters in size. I'm struggling to think of a condition to realloc memory with, e.g
if condition{
memoryofarray += x amount
realloc(array, memoryofarray)
}
What exactly uses the memory in the char**? I was under the impression that each byte corresponds to how many lines they can hold, i.e. malloc(10) would allow the array to hold 10 strings. I need to know this to establish conditions + to know how much to increment the memory allocated to the array by.
Also, curiously, when I malloced
array[num] = malloc(0)
before assigning a string to that array element, it worked without problems. Don't you need to at least have strlen amount of bytes to store strings? This is confusing me massively
This line:
char **array = malloc(10);
allocates 10 bytes, however, remember that a pointer is not the same size as a byte.
Therefore you need to make sure you allocate an array of sufficient size by using the size of the related type:
char **array = malloc(10 * sizeof(char*));
Now that you have an array of 10 pointers you need to allocate memory for each of the 10 strings, e.g.
array[0] = malloc(25 * sizeof(char));
Here sizeof(char) is not needed but I added it to make it more obvious how malloc works.
If you want to hold 10 strings then you need to allocate memory for 10 char *'s and then allocate memory to those char pointers .You allocate memory of 10 bytes( not enough for 10 char *'s ) .Allocate like this -
char **array = malloc(10*sizeof(char *)); // allocate memory for 10 char *'s
And then do what you were doing -
array[num] = malloc(strlen(source)+1) // allocate desired memory to each pointer
note - take care that num is initialized and does not access out of bound index.
This will allocate enough memory for 10 pointers to char (char*) in array
char **array = malloc(10*sizeof(array[0]));
On a 64bit system the size of a char* is 8 bytes = 64 bits. The size of a char is typically 1 byte = 8 bits.
The advantage of using sizeof(array[0]) instead sizeof(char*) is that it's easier to change the type of array in the future.
char** is pointer to a pointer to char. It may point to the start of a memory block in the heap with pointers to char. Similarly char* is a pointer to char and it may point to the start of a memory block of char on the heap.
If you write beyond the allocated memory you get undefined behaviour. If you are lucky it may actually behave well! So when you do for example :
array[num] = malloc(0);
you may randomly not get a segmentation fault out of (good) luck.
Your use of realloc is wrong. realloc may have to move the memory block whose size you want to increase in which case it will return a new pointer. Use it like this :
if (condition) {
memoryofarray += amount;
array = realloc(array, memoryofarray);
}
Rather than allocating memory using the fault-prone style
pointer = malloc(n); // or
pointer = malloc(n * sizeof(type_of_pointer));
Use
pointer = malloc(sizeof *pointer * n);
Then
// Bad: certainly fails to allocate memory for 10 `char *` pointers
// char **array = malloc(10);
// Good
char **array = malloc(sizeof *array * 10);
how does memory with these arrays work?
If insufficient memory is allocated, it does not work. So step 1: allocate sufficient memory.
Concerning array[num] = malloc(0). An allocation of 0 may return NULL or a pointer to no writable memory or a pointer to some writable memory. Writing to that pointer memory is undefined behavior (UB) in any of the 3 cases. Code may crash, may "work", it is simply UB. Code must not attempt writing to that pointer.
To be clear: "worked without problems" does not mean code is correct. C is coding without a net. Should code do something wrong (UB), the language is not obliged to catch that error. So follow safe programming practices.
First allocate an array of pointers:
char* (*array)[n] = malloc( sizeof(*array) );
Then for each item in the array, allocate the variable-length strings individually:
for(size_t i=0; i<n; i++)
{
(*array)[i] = malloc( some_string_length );
}
Is there any way to free some part of memory you created by using malloc();
suppose:-
int *temp;
temp = ( int *) malloc ( 10 * sizeof(int));
free(temp);
free() will release all 20 byte of memory but suppose i only need 10 bytes. Can i free last 10 bytes.
You should use the standard library function realloc. As the name suggests, it reallocates a block of memory. Its prototype is (contained in the header stdlib.h)
void *realloc(void *ptr, size_t size);
The function changes the size of the memory block pointed to by ptr to size bytes. This memory block must have been allocated by a malloc, realloc or calloc call. It is important to note that realloc may extend the older block to size bytes, may keep the same block and free the extra bytes, or may allocate an entirely new block of memory, copy the content from the older block to the newer block, and then free the older block.
realloc returns a pointer to the block of reallocated memory. If it fails to reallocate memory, then it returns NULL and the original block of memory is left untouched. Therefore, you should store the value of ptr in a temp variable before calling realloc else original memory block will be lost and cause memory leak. Also, you should not cast the result of malloc - Do I cast the result of malloc?
// allocate memory for 10 integers
int *arr = malloc(10 * sizeof *arr);
// check arr for NULL in case malloc fails
// save the value of arr in temp in case
// realloc fails
int *temp = arr;
// realloc may keep the same block of memory
// and free the memory for the extra 5 elements
// or may allocate a new block for 5 elements,
// copy the first five elements from the older block to the
// newer block and then free the older block
arr = realloc(arr, 5 * sizeof *arr);
if(arr == NULL) {
// realloc failed
arr = temp;
}
You can use realloc function provided by the standard c library.
C99 Standard 7.20.3.4-1: The realloc function:
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.
I'm fairly new to C, and just now starting to venture into the realm of dynamically allocated arrays.
I think i've got mostly malloc down, but had some questions on realloc:
Can realloc be used for anything else besides adding memory space to pointers?
Does the size variable always have to be an int?
Would something like the below work?
float *L = NULL;
int task_count = 5;
L = (float*) realloc (L, task_count * sizeof(float));
If I wanted to increase that space further (by one in this case), could I just use something like the following?
L = (float*) realloc (L, 1 * sizeof(float));
Seems deceptively simple, which tells me I'm possibly missing something.
In case that ptr is a null pointer, the function behaves like malloc, assigning a new block of size bytes and returning a pointer to its beginning.
void * realloc (void* ptr, size_t size);
ptr - Pointer to a memory block previously allocated with malloc, calloc or realloc.
Alternatively, this can be a null pointer, in which case a new block is allocated (as if
malloc was called).
sizeNew - size for the memory block, in bytes. size_t is an unsigned integral type.
sizeNew has to define the entirety of the memory you want, could be smaller, could be larger!
Yes, you can also reduce memory space
Nah, why that? It takes void* as 1st parameter and returns void*
Yes, but no need to cast!
And finally, you have to tell the total memory sizeto the function.
I created a dynamic array ,and i need to initialize all the members to 0.
How can this be done in C?
int* array;
array = (int*) malloc(n*sizeof(int));
In this case you would use calloc():
array = (int*) calloc(n, sizeof(int));
It's safe to assume that all systems now have all zero bits as the representation for zero.
§6.2.6.2 guarantees this to work:
For any integer type, the object representation where all the bits are
zero shall be a representation of the value zero in that type.
It's also possible to do a combination of malloc() + memset(), but for reasons discussed in the comments of this answer, it is likely to be more efficient to use calloc().
memset(array, 0, n*sizeof(int));
Or alternatively, you could allocate your block of memory using calloc, which does this for you:
array = calloc(n, sizeof(int));
calloc documentation:
void *calloc(size_t nmemb, size_t size);
The calloc() function allocates memory for an array of nmemb elements of size bytes each and returns a pointer to the allocated memory. The memory is set to zero. ...
Use calloc function (usage example):
int *array = calloc(n, sizeof(int));
From calloc reference page:
void *calloc(size_t nelem, size_t elsize);
The calloc() function shall allocate unused space for an array of nelem elements each of whose size in bytes is elsize. The space shall be initialized to all bits 0.
memset(array, 0, n * sizeof *array);
for (i=0; i<x; ++i){
array[i]=0;
}
That should do the trick. I guess you have to make a loop that makes 0 every element in the array. Memset could also work for you.