Pregunta

Recibo algunas anulaciones de datos extrañas e intermitentes (<5% del tiempo) en parte de mi código cuando llamo memset().El problema es que esto generalmente no sucede a menos que el código se ejecute durante un par de días, por lo que es difícil detectarlo en el acto.

Estoy usando el siguiente código:

char *msg = (char*)malloc(sizeof(char)*2048);
char *temp = (char*)malloc(sizeof(char)*1024);
memset(msg, 0, 2048);
memset(temp, 0, 1024);
char *tempstr = (char*)malloc(sizeof(char)*128);

sprintf(temp, "%s %s/%s %s%s", EZMPPOST, EZMPTAG, EZMPVER, TYPETXT, EOL);
strcat(msg, temp);

//Add Data
memset(tempstr, '\0', 128);
wcstombs(tempstr, gdevID, wcslen(gdevID));
sprintf(temp, "%s: %s%s", "DeviceID", tempstr, EOL);
strcat(msg, temp);

Como puede ver, no estoy intentando usar memset con un tamaño mayor que el asignado originalmente con malloc()

¿Alguien ve qué podría estar mal con esto?

¿Fue útil?

Solución

malloc puede regresar NULL si no hay memoria disponible.No estás comprobando eso.

Otros consejos

Hay un par de cosas.estas usando sprintf que es inherentemente inseguro;a menos que esté 100% seguro de que no va a exceder el tamaño del buffer, casi debería siempre preferir snprintf.Lo mismo se aplica a strcat;Prefiero la alternativa más segura. strncat.

Obviamente esto puede no solucionar nada, pero va un paso adelante. largo manera de ayudar a detectar lo que de otro modo podría resultar muy molesto detectar errores.

Malloc puede devolver nulo si no hay memoria disponible.No estás revisando para eso.

Estás en lo correcto...No pensé en eso porque estaba monitoreando la memoria y había suficiente espacio libre.¿Hay alguna manera de que haya memoria disponible en el sistema pero que malloc falle?

Sí, si la memoria está fragmentada.Además, cuando dice "supervisión de la memoria", puede haber algo en el sistema que ocasionalmente consume mucha memoria y luego la libera antes de que usted se dé cuenta.Si tu llamada a malloc ocurre entonces, no habrá memoria disponible.-- joel

De cualquier manera... agregaré ese cheque :)

wcstombs no obtiene el tamaño del destino, por lo que, en teoría, puede producirse un desbordamiento del búfer.

¿Y por qué estás usando sprintf ¿Con lo que supongo que son constantes?Solo usa:

EZMPPOST" " EZMPTAG "/" EZMPVER " " TYPETXT EOL

C y C++ combinan declaraciones literales de cadena en una sola cadena.

¿Has probado a usar Valgrind?Suele ser la forma más rápida y sencilla de depurar este tipo de errores.Si está leyendo o escribiendo fuera de los límites de la memoria asignada, lo marcará.

Estás usando sprintf que es inherentemente inseguro;A menos que esté 100% positivo de que no va a exceder el tamaño del búfer, casi siempre debe preferir snprintf.Lo mismo se aplica a strcat;Prefiere el strncat alternativo más seguro.

Sí.....Últimamente uso principalmente .NET y los viejos hábitos son difíciles de eliminar.Probablemente saqué ese código de algo más que se escribió antes de mi tiempo...

Pero intentaré no usarlos en el futuro;)

Sabes que puede que ni siquiera sea tu código...¿Hay otros programas en ejecución que podrían tener una pérdida de memoria?

Podría ser tu procesador.Algunas CPU no pueden abordar bytes individuales y requieren que usted trabaje en palabras o tamaños de fragmentos, o que tengan instrucciones que solo se pueden usar en datos alineados con palabras o fragmentos.

Por lo general, el compilador los conoce y los soluciona, pero a veces puede asignar una región como bytes y luego intentar abordarla como una estructura o un campo de más ancho que un byte, y el compilador no lo detectará. , pero el procesador generará una excepción de datos más adelante.

No sucedería a menos que estés usando una CPU inusual.ARM9 hará eso, por ejemplo, pero i686 no.Veo que está etiquetado como Windows Mobile, así que tal vez tengas este problema de CPU.

en lugar de hacer malloc seguido por memset, deberías estar usando calloc lo que borrará la memoria recién asignada.Aparte de eso, haz lo que dijo Joel.

NB tomó prestados algunos comentarios de otras respuestas y los integró en un todo.El código es todo mío...

  • Verifique sus códigos de error.P.ej.malloc puede devolver NULL si no hay memoria disponible.Esto podría estar provocando la cancelación de sus datos.
  • sizeof(char) es 1 por definición
  • Utilice snprintf, no sprintf, para evitar desbordamientos del búfer
    • Si EZMPPOST, etc. son constantes, entonces no necesita una cadena de formato, simplemente puede combinar varias cadenas literales como STRING1 " " STRING2 " " STRING3 y strcat todo.
  • Estás utilizando mucha más memoria de la que necesitas.
  • Con un cambio menor, no es necesario llamar a memset en primer lugar.Nada realmente requiere cero inicialización aquí.

Este código hace lo mismo, de forma segura, se ejecuta más rápido y utiliza menos memoria.

    // sizeof(char) is 1 by definition. This memory does not require zero
    // initialisation. If it did, I'd use calloc.
    const int max_msg = 2048;
    char *msg     = (char*)malloc(max_msg);
    if(!msg)
    {
       // Allocaton failure
       return;
    }
    // Use snprintf instead of sprintf to avoid buffer overruns
    // we write directly to msg, instead of using a temporary buffer and then calling
    // strcat. This saves CPU time, saves the temporary buffer, and removes the need
    // to zero initialise msg.
    snprintf(msg, max_msg, "%s %s/%s %s%s", EZMPPOST, EZMPTAG, EZMPVER, TYPETXT, EOL);

   //Add Data
   size_t len = wcslen(gdevID);
   // No need to zero init this
   char* temp = (char*)malloc(len);
   if(!temp)
   {
      free(msg);
      return;
   }
   wcstombs(temp, gdevID, len);
   // No need to use a temporary buffer - just append directly to the msg, protecting 
   // against buffer overruns.
   snprintf(msg + strlen(msg), 
           max_msg - strlen(msg), "%s: %s%s", "DeviceID", temp, EOL);
   free(temp);
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top