tags:

views:

149

answers:

4

I need to recv() data from a socket and store it into a buffer, but I need to make sure get all of the data so I have things in a loop. So to makes sure I don't run out of room in my buffer, I'm trying to use realloc to resize the memory allocated to the buffer. So far I have:

 // receive response
 int i = 0;
 int amntRecvd = 0;
 char *pageContentBuffer = (char*) malloc(4096 * sizeof(char));
 while ((amntRecvd = recv(proxySocketFD, pageContentBuffer + i, 4096, 0)) > 0) {
  i += amntRecvd;
  realloc(pageContentBuffer, 4096 + sizeof(pageContentBuffer));
 }

However, this doesn't seem to be working properly since Valgrind is complaining "valgrind: the 'impossible' happened:". Any advice as to how this should be done properly?

Thanks, Hristo

update... I realized I was using realloc incorrectly. Here is a revised version:

 int i = 0;
 int amntRecvd = 0;
 char *pageContentBuffer = (char*) malloc(4096 * sizeof(char));
 while ((amntRecvd = recv(proxySocketFD, pageContentBuffer + i, 4096, 0)) > 0) {
  i += amntRecvd;
  char *temp = realloc(pageContentBuffer, 4096 + sizeof(pageContentBuffer));
  if (temp != NULL) {
   pageContentBuffer = temp;
  }
 }

However, valgrind still is complaining:

==25812== Syscall param socketcall.recvfrom(buf) points to unaddressable byte(s)
==25812==    at 0x33B880DAA1: recv (in /lib64/libpthread-2.5.so)
==25812==    by 0x401D78: tunnelURL (proxy.c:371)
==25812==    by 0x40142A: client_thread (proxy.c:194)
==25812==    by 0x33B8806616: start_thread (in /lib64/libpthread-2.5.so)
==25812==    by 0x33B7CD3C2C: clone (in /lib64/libc-2.5.so)
==25812==  Address 0x5642768 is 0 bytes after a block of size 4,104 alloc'd
==25812==    at 0x4A0590B: realloc (vg_replace_malloc.c:306)
==25812==    by 0x401D47: tunnelURL (proxy.c:373)
==25812==    by 0x40142A: client_thread (proxy.c:194)
==25812==    by 0x33B8806616: start_thread (in /lib64/libpthread-2.5.so)
==25812==    by 0x33B7CD3C2C: clone (in /lib64/libc-2.5.so)
+2  A: 

Perhaps there is an issue because you are misusing realloc(). You need to see if it returns a new pointer, and if so, store that pointer.

// receive response
int i = 0;
int amntRecvd = 0;
char *pageContentBuffer = (char*) malloc(4096 * sizeof(char));
while ((amntRecvd = recv(proxySocketFD, pageContentBuffer + i, 4096, 0)) > 0) {
    i += amntRecvd;
    pageContentBuffer = realloc(pageContentBuffer, 4096 + sizeof(pageContentBuffer));
}
WhirlWind
+3  A: 

Aside from what @whirlwind said, there's also a second issue:

sizeof does not return the amount of memory previously allocated, it is actually a compile-time construct which is equivalent to sizeof(char *), i.e. the size of a character pointer.

You will need to keep track of the length of your buffer manually in a variable. There is no standard way to "ask" how much memory has been allocated by malloc/realloc.

John Kugelman
Yup, sizeof(pageContentBuffer) is the same as sizeof (char *)
WhirlWind
A: 

Look up realloc.

sizeof - is a compile time value - not a runtime

it is possible for realloc to return 0;

try this...

// receive response
int i = 0;
int amntRecvd = 0;
int currentSize = 4096;
int oldSize = currentSize;
char *pageContentBuffer = (char*) malloc(currentSize);
while ((amntRecvd = recv(proxySocketFD, pageContentBuffer + i, 4096, 0)) > 0) {
    i += amntRecvd;
    oldSize = currentSize; 
    currentSize += 4096; 
    char *newBuffer = malloc(currentSize); 
    memcpy(newBuffer,pageContentBuffer,oldSize); 
    free(pageContentBuffer); 
    pageContentBuffer = newBuffer
}

Your best bet is to reallocate, copy and then delete the memory explicitely - realloc is quirky.

Romain Hippeau
can you give me a specific example of "Your best bet is to reallocate, copy and then delete the memory explicitely"
Hristo
@Hristoint oldSize = currentSize; currentSize += 4096;char *newBuffer = malloc(currentSize);memcpy(newBuffer,pageContentBuffer,oldSize);free(pageContentBuffer);pageContentBuffer = newBuffer;I have not verified it, but that is the gist
Romain Hippeau
@Hristo - I updated the code
Romain Hippeau
Thanks a lot Romain. This seems to fix my issues, however Valgrind is complaining that "newBuffer" memory is leaking. I tried fixing it with free()-ing in several places but each caused more problems. Any suggestions?
Hristo
@Romain. Figured out how to free the newBuffer. I had to free after the function returned for a new variable that I made. Thanks a lot!
Hristo
@Hristo - I do not see it - I am looking. - Are you sure it is newBuffer ?
Romain Hippeau
On which platforms is realloc "quirky"? I've never had any problems with it.
Dietrich Epp
@Hristo - So you had to free pageContentBuffer when you were done with it, right ?
Romain Hippeau
The variable I had to free is not in the code I have shown you. The problem is that I was allocating memory for newBuffer and then the pointer is reassigned to pageContentBuffer, which is then returned by the function to a variable you don't know about which I need to free after I'm done. Does that make sense?
Hristo
@Dietrich Epp - I used to have issues with it on OS/2 and also on older windows - I have since never used it and therefore avoided any issues
Romain Hippeau
@Hristo Not really but if you are good then I am happy :)
Romain Hippeau
@Romain :) I'm sorry Romain but I can't explain it any better. More or less, yes I had to free pageContentBuffer after I'm done with it, but its not free(pageContentBuffer) because pageContentBuffer gets returned by the function. So char *pageContent = tunnelURL(url); free(pageContent); I am good so thanks :)
Hristo
-1: there's no need to reimplement realloc. Your example has the same problem you identify as an issue with realloc -- the malloc might return 0.
Chris Dodd
Yes it may - As I said above I have had some issues with realloc in the past on certain OS's and it obviously fixed his problem. There are some versions of realloc that do not move the memory if they cannot expand the memory they fail
Romain Hippeau
@Hristo - Do make sure you do check that malloc does return a value > 0 as per Chris Dodd
Romain Hippeau
+1  A: 

Your main problem is that you're reallocing the wrong amount of memory. You want

realloc(pageContentBuffer, 4096 + i);

sizeof(pageContentBuffer) is just sizeof(char *), which means you're reallocing far less than you need for the second read.

Chris Dodd