How do you properly resize an array using realloc
so that the newly allocated array can have the data from the previous array plus the newly received data
int receiver (int soc_desc, char * buffer)
{
char *arr;
size_t received =0 , total_received=0;
char buff[MAX 1];
memset(buff , 0 , MAX 1);
while (1)
{
received = recv(soc_desc, buff , MAX , 0 );
if (received <= 0 )
break;
else
{
total_received = total_received strlen(buff);
buffer = realloc(buffer, total_received);
printf("Total: %ld received: %ld \n",total_received , received);
strcat(buffer, buff);
}
printf("%s\n",buff);
}
printf("Final result: %s \n", buffer);
in this function, we pass a socket descriptor and a char *buffer = malloc(MAX)
we receive data and add it to the allocated buffer and then try to reallocate the buffer for the next chunk of data, is there a way to resize the original malloc
d buffer
so that I can fit more characters in it without creating a new pointer for realloc
each time it is called
when I compile and run this code with valgrind I get
==13850== Address 0x4a5c0e3 is 0 bytes after a block of size 3 alloc'd
==13850== at 0x483DFAF: realloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==13850== by 0x109884: ??? (in /home/User/Desktop/test)
==13850== by 0x109476: ??? (in /home/User/Desktop/test)
==13850== by 0x48870B2: (below main) (libc-start.c:308)
.
.
.
.
==13850== HEAP SUMMARY:
==13850== in use at exit: 27 bytes in 1 blocks
==13850== total heap usage: 22 allocs, 22 frees, 15,807 bytes allocated
since buffer
is a function parameter I used free(buffer)
outside the function
CodePudding user response:
Compile using -g3 -ggdb3 -Wall -Wextra
flags to get line number of error in valgrind
and other sort of warnings.
Also, realloc()
copies previous data to new one.
Some Points:
total_received = total_received strlen(buff);
can be written astotal_received = strlen(buff);
- You need to take
buffer
aschar **buffer
and then de-reference it like(*buffer)
, so that modification ofbuffer
can be done permanently in another function's scope "%zu"
is valid format specifier forsize_t
- Make sure that
buffer
is heap-allocated in its definition scope memset(buff , 0 , MAX 1);
can be written aschar buff[MAX 1] = {};
- I don't see any use of
arr
variable inreceiver()
function - NOTE: Make sure that new size for
buffer
is larger than the previous size - Always check whether heap allocation was successful or not, by checking the pointer against
NULL
, eg.,if(!buffer) { /* error */ }
- Pass
buffer
like&buffer
[give address ofbuffer
toreceiver()
function] received
isunsigned long int
AKAsize_t
which means it starts from 0, hence checking for less than 0 is not required, instead check for(received == 0)
- Use
memcpy()
to appendbuff
to*buffer
by limiting the length ofbuff
- Append null terminating character at the very end of
*buffer
Final Code:
int receiver(int soc_desc, char **buffer)
{
char *arr; // idk
size_t received = 0, total_received = 0;
char buff[MAX 1] = {}; // every element is now 0
while (1)
{
received = recv(soc_desc, buff, MAX, 0);
if (received == 0)
break;
else
{
total_received = received;
(*buffer) = realloc(*buffer, total_received 1);
if (*buffer == NULL) // error occurred
{
exit(EXIT_FAILURE);
}
printf("Total: %zu received: %zu\n", total_received, received);
memcpy(*buffer, buff, received);
(*buffer)[total_received 1] = 0; // nul terminating character
}
printf("%s\n", buff);
}
printf("Final result: %s \n", *buffer);
/*your rest of the code */
CodePudding user response:
According to the documentation:
Reallocates the given area of memory. It must be previously allocated by
malloc()
,calloc()
orrealloc()
and not yet freed with a call to free or realloc. Otherwise, the results are undefined.The reallocation is done by either:
a) expanding or contracting the existing area pointed to by
ptr
, if possible. The contents of the area remain unchanged up to the lesser of the new and old sizes. If the area is expanded, the contents of the new part of the array are undefined. (*)b) allocating a new memory block of size
new_size
bytes, copying memory area with size equal the lesser of the new and the old sizes, and freeing the old block.If there is not enough memory, the old memory block is not freed and null pointer is returned. (#)
The formatting (bold text) and (*) and (#) have been added, and were not in the quoted text.
Solving (#):
bool realloc_buffer(void **buffer, size_t new_size)
{
void *tmp = *buffer;
*buffer = realloc(*buffer, new_size);
if (!*buffer) { // Realloc failed: restore the old pointer.
*buffer = tmp;
return false;
}
return true;
}
Then in your code:
int receiver (int soc_desc, char **buffer)
{
// ...
if (!realloc_buffer(buffer, old_size total_received 1)) { // You should know the old size
// Handle failure
}
}
You said:
... so that the newly allocated array can have the data from the previous array plus the newly received data
According to (*), you have to manually append the new data.
int receiver (int soc_desc, char **buffer)
{
// ...
char *copy = malloc(sizeof(char*) * (old_size 1));
// Make a copy of the old buffer
memcpy(copy, buffer, old_size 1);
if (!realloc_buffer(buffer, old_size total_received 1)) { // You should know the old size
// Handle failure
} else {
memcpy(buffer old_size * sizeof(char*), copy, total_received 1);
}
free(copy);
// ...
}