I'm actually learning C programming and my school actually doesn't allow us to use calloc / realloc without reprogramming them. That's why I'm asking for help.
Here is my problem :
I want to use void *
to make my code reusable but I encounter the problem "dereferencing void *
pointer" when I try to run through my array. I'm unable to pick up the type of the final pointer.
Here is my functions :
#include <stdlib.h>
void *my_calloc(size_t size, size_t n) //n = number of bytes your type : sizeof(<whatever>)
{
void *ptr = NULL;
if (size < 1 || n < 1)
return (NULL);
ptr = malloc(n * (size + 1));
if (ptr == NULL)
return (NULL);
for (int i = 0; i != (n * (size + 1)); i++) {
*ptr = NULL; //Here is my problem
ptr++;
}
return (ptr);
}
void *my_realloc(void *src, size_t size, size_t n)
{
void *dst = NULL;
int dst_len = 0;
if (src == NULL || size < 0 || n < 1)
return (NULL);
dst_len = my_strlen(src) + size;
if (dst_len == my_strlen(src))
return (src);
dst = my_calloc(dst_len, n);
if (dst == NULL)
return (NULL);
for (int i = 0; src[i] != NULL;i++)
dst[i] = src[i]; //Here is the same problem...
free(src);
return (dst);
}
I just find a problem while I was writing my post, my my_strlen
function can only take a char *... so I would need a function my_strlen
looking like :
int my_strlen(void *str)
{
int len = 0;
while (str[len] != NULL) { //same problem again...
len++;
}
return (len);
}
A typical function where i call calloc / malloc would be :
int main(void)
{
char *foo = NULL;
int size = 0;
int size_to_add = 0;
size = <any size>;
//free(foo); //only if foo has been malloc before
foo = my_calloc(size, typeof(*foo));
//something
size_to_add = <any size>;
foo = my_realloc(foo, size_to_add, sizeof(*foo))
//something
free(foo);
return (0);
}
Thank you for trying to help me.
my_calloc()
has various troubles:
Attemptted pointer math on a void *
This is undefined behavior (UB).
Instead make ptr
a character pointer.
// void *ptr = NULL;
unsigned char *ptr = NULL;
...
ptr++;
Attempt to de-reference a void *
This is also UB.
Instead make ptr
a character pointer.
// void *ptr = NULL;
unsigned char *ptr = NULL;
...
// *ptr = NULL;
*ptr = '\0';
my_calloc()
allocates more memory than calloc()
To do the same as calloc()
, do not add one.
// ptr = malloc(n * (size + 1));
ptr = malloc(n * size);
No overflow protection
my_calloc()
does not detect overflow with n * (size + 1)
. A test is
// Note: it is known n > 0 at this point
if (SIZE_MAX/n > size+1) return NULL;
// or if OP drop the + 1 idea,
if (SIZE_MAX/n > size) return NULL;
my_realloc()
has various troubles:
Different signature
I'd expect the goal of "school actually doesn't allow us to use calloc / realloc without reprogramming them" was meant to create a realloc()
substitute of which my_realloc()
is not. If a different function is desired, consider a new name
void *my_realloc(void *src, size_t size, size_t n)
// does not match
void *realloc(void *ptr, size_t size);
Failure to handle a shrinking allocation
The copying of data does not take into account that the new allocation may be smaller than the prior one. This leads to UB.
Unneeded code
size < 0
is always false
Memory leak
The below code does not free src
before returning. Further, it does not allocate anything when n>0
. This differs from calloc(pit, 0)
and calloc(NULL, 42)
.
// missing free, no allocation
if (src == NULL || size < 0 || n < 1) {
return (NULL);
}
Assumed string
my_strlen(src)
assume src
points to a valid string. calloc()
does not assume that.