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 mallocd 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
bufferaschar **bufferand then de-reference it like(*buffer), so that modification ofbuffercan be done permanently in another function's scope "%zu"is valid format specifier forsize_t- Make sure that
bufferis 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
arrvariable inreceiver()function - NOTE: Make sure that new size for
bufferis 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
bufferlike&buffer[give address ofbuffertoreceiver()function] receivedisunsigned long intAKAsize_twhich means it starts from 0, hence checking for less than 0 is not required, instead check for(received == 0)- Use
memcpy()to appendbuffto*bufferby 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_sizebytes, 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);
// ...
}
