Clases de socket C++ - TCP: problemas de recepción

Un registro de mis problemas

creé mi propia clase de socket para poder enviar y recibir peticiones http.
Pero todavía tengo algunas preguntas. El siguiente código (mi función receptora) sigue siendo problemático y a veces colapsa.
Traté de depurarlo, pero debe estar en algún lugar de la gestión aritmética/Memoria del puntero.
int Socket::Recv(char *&vpszRecvd)
{
 //vpszRecvd = NULL;
 int  recvsize = 0;
 char TempBuf[1024];
 int  Result = 0;
 char* temp;


 do
 {
  memset(TempBuf, 0, sizeof(TempBuf));

  Result = recv( this->sSocket, TempBuf, sizeof(TempBuf) -1, 0 );
  if (recvsize == 0)
   recvsize = Result;

  if ( Result > 0 )
  {
   if ( vpszRecvd != NULL )
   {
    if (temp == NULL)
    {
     temp = (char*)calloc(recvsize + 1, sizeof(char));
    }
    else
    {
     realloc(temp, recvsize + 1);
    }
    if (temp == NULL)
     return 0;

    memcpy(temp, vpszRecvd, recvsize);
    realloc(vpszRecvd, recvsize + Result);

    if (vpszRecvd == NULL)
     return 0;

    memset(vpszRecvd, 0, recvsize + Result);
    memcpy(vpszRecvd, TempBuf, Result);
    memcpy(vpszRecvd + recvsize, TempBuf, Result);
    recvsize += Result; 
   }
   else
   {
    realloc(vpszRecvd, Result);

    if (vpszRecvd == NULL)
     return 0;

    memset(vpszRecvd, 0, Result);
    memcpy(vpszRecvd, TempBuf, Result);
    recvsize += Result;
   }
  }
  else if (  Result == 0 )
  {
   return recvsize;

  }
  else //if (  Result == SOCKET_ERROR )
  {
   closesocket(this->sSocket);
   this->sSocket = INVALID_SOCKET;
   return SOCKET_ERROR;
  }
 }
 while( Result > 0 );

 return recvsize;
}
¿Alguien ha visto algo que pueda causar un accidente, o alguien tiene un ejemplo mejor/más rápido/más pequeño, más estable, como Cómo recibir paquetes completos a través de recv ()?
No puedo usar cadenas, pero debo usar caracteres.
Gracias por tu ayuda.

Detalles de la solución

usted no inicializa temp, y además, su llamada a realloc es incorrecta. Debería ser:
temp = realloc (temp, recvsize+1);
Cuando llama a realloc como está, descarta la nueva dirección, lo más probable es que la antigua ya haya sido liberada. Cuando intentas citarlo, todas las apuestas se cancelan.
La razón por la que realloc devuelve una nueva dirección es que si el bloque actual está rodeado en el área de memoria, el Buffer de extensión puede tener que moverlo (en otras palabras, no puede extenderse sólo a los bloques libres que siguen). En este caso, se crea un nuevo bloque en la arena y se libera el contenido transmitido desde el bloque antiguo. Si esto ocurre, debe obtener el valor de retorno de realloc.
Recuerde que realloc no tiene que devolver un nuevo puntero, por ejemplo, si hay suficiente espacio libre detrás del bloque para satisfacer el nuevo tamaño, o si desea reducir el tamaño, puede darle el mismo puntero.
Si el bloque no se puede extender, también puede devolver null, y usted debe notarlo, especialmente porque:
temp = realloc (temp, newsize);
Cuando devuelve null, causa una fuga de memoria (no libera bloques antiguos).
Hay algunas cosas más:
  • rara vez necesita usar calloc, especialmente en este caso, porque todavía está copiando en memoria.
  • Del mismo modo, si desea establecer el bloque de memoria a 0 inmediatamente a través de memset, no necesita establecer memcpy a 0.
  • si inicializa temp a NULL, simplemente use realloc sin probarlo. Esto se debe a que realloc(NULL,7) es idéntico a malloc(7) - realloc es totalmente capaz de empezar con un puntero nulo.
  • debido a que no necesita calloc, esto es sólo para educación - por definición sizeof(char) siempre es 1.
  • parece que está haciendo una gran cantidad de replicación innecesaria de datos.
  • ¿Por qué no empezamos con algo más simple? Ahora, esto es exactamente lo que pensé, por lo que puede haber algunos errores, pero al menos fue eliminado del coloso que movió la memoria del problema: -, por lo que debería ser más fácil de depurar.
    Básicamente se puede dividir en:
  • inicializa un mensaje vacío.
  • entra en un bucle infinito.
  • obtiene un segmento.
  • si se produce un error, libere todo y devuelva el error.
  • devuelve el mensaje actual si no hay más segmentos.
  • crea espacio para el nuevo segmento al final del mensaje.
  • si no puede crear un espacio, libere todo y devuelva un mensaje vacío.
  • añade segmentos al mensaje y redimensiona el mensaje.
  • El Código es el siguiente:
    int Socket::Recv(char *&vpszRecvd) {
        int  recvsize = 0;
        char TempBuf[1024];
        int  Result = 0;
        char *oldPtr;
    
        // Optional free current and initialise to empty.
    
        //if (vpszRecvd != NULL) free (vpszRecvd);
        vpszRecvd = NULL;
    
        // Loop forever (return inside loop on end or error).
    
        do {
            Result = recv( this->sSocket, TempBuf, sizeof(TempBuf) -1, 0 );
    
            // Free memory, close socket on error.
    
            if (Result < 0) {
                free (vpszRecvd);
                closesocket(this->sSocket);
                this->sSocket = INVALID_SOCKET;
                return SOCKET_ERROR;
            }
    
            // Just return data and length on end.
    
            if (Result == 0) {
                return recvsize;
            }
    
            // Have new data, use realloc to expand, even for initial malloc.
    
            oldPtr = vpszRecvd;
            vpszRecvd = realloc (vpszRecvd, recvsize + Result);
    
            // Check for out-of-memory, free memory and return 0 bytes.
    
            if (vpszRecvd == NULL) {
                free (oldPtr);
                return 0;
            }
    
            // Append it now that it's big enough and adjust the size.
    
            memcpy (&(vpszRecvd[recvsize], TempBuf, Result);
            recvsize += Result;
        } while (1);
    }