mplab - Usando snprintf para evitar sobrecargas de búfer
sprintf signed int (6)
Como han dicho otros, no necesitas el -1 en este caso. Si la matriz es de tamaño fijo, usaría strncpy
lugar. Fue hecho para copiar cadenas, sprintf
fue hecho para hacer un formateo difícil. Sin embargo, si el tamaño de la matriz es desconocido o si está tratando de determinar cuánto almacenamiento es necesario para una cadena con formato. Esto es lo que realmente me gusta de la versión estándar especificada de snprintf
:
char* get_error_message(char const *msg) {
size_t needed = snprintf(NULL, 0, "%s: %s (%d)", msg, strerror(errno), errno);
char *buffer = malloc(needed+1);
sprintf(buffer, "%s: %s (%d)", msg, strerror(errno), errno);
return buffer;
}
Combine esta función con va_copy
y podrá crear operaciones de cadena formateadas muy seguras.
Estoy usando snprintf
esta manera para evitar una saturación del búfer:
char err_msg[32] = {0};
snprintf(err_msg, sizeof(err_msg) - 1, "[ ST_ENGINE_FAILED ]");
Agregué el -1
para reservar espacio para el terminador nulo en caso de que la cadena tenga más de 32 bytes de longitud.
¿Estoy correcto en mi pensamiento?
Plataforma:
- CGC 4.4.1
- C99
No hay necesidad de -1. C99 snprintf
siempre termina en cero. El argumento de tamaño especifica el tamaño del búfer de salida, incluido el terminador cero. El código, por lo tanto, se convierte en
char err_msg[32];
int ret = snprintf(err_msg, sizeof err_msg, "[ ST_ENGINE_FAILED ]");
ret
contiene el número real de caracteres impresos ( excluyendo el terminador cero).
Sin embargo, no confunda con _snprintf
de Microsoft (anterior a C99), que no termina en nulo y, para el caso, tiene un comportamiento completamente diferente (por ejemplo, devolver -1
lugar de la longitud impresa en caso de que el búfer no sea grande suficiente). Si usa _snprintf
, debe usar el mismo código que en su pregunta.
No necesitas el -1, como dice la referencia:
Las funciones snprintf () y vsnprintf () no escriben más que bytes de tamaño (incluido el ''/ 0'').
Note la parte "incluyendo la parte final ''/ 0''"
Para el ejemplo dado, deberías estar haciendo esto en su lugar:
char err_msg[32];
strncpy(err_msg, "[ ST_ENGINE_FAILED ]", sizeof(err_msg));
err_msg[sizeof(err_msg) - 1] = ''/0'';
o mejor:
char err_msg[32] = "[ ST_ENGINE_FAILED ]";
Según snprintf(3)
:
Las funciones
snprintf()
yvsnprintf()
no escriben más que bytes desize
(incluido el''/0''
).
sizeof devolverá el número de bytes que el tipo de datos usará en la memoria, no la longitud de la cadena. Por ejemplo, sizeof (int) devuelve ''4'' bytes en un sistema de 32 bits (bueno, dependiendo de la implementación, supongo). Ya que usa una constante en su matriz, puede pasarla felizmente a la printf.