¿Por qué ocurrió esta situación? Problema de librería C al usar Windows WSL (Ubuntu 20.04).
Me encontré con un problema extraño mientras usaba gcc para la biblioteca c en la función strcpy y strtol.
Probé en dos situaciones y obtuve resultados muy diferentes.
//#The bad code is "res=68"
#include
#include
#include
#include
int main() {
char buf[10];
char* endptr;
int x;
int res;
memset(buf, 0, sizeof(buf));
res=0;
strcpy(buf, "a678b");
while (*(buf) != '\0') {
x = strtol(buf, &endptr, 10);
if (x == 0) {
strcpy(buf, (endptr + 1));
}
else {
strcpy(buf, endptr);
}
res+= x;
}
printf("%d", res);
return 0;
}
Después de cambiar a la siguiente área, se puede obtener el valor correcto: 678.
Pero, ¿por qué?
while (*(buf) != '\0') {
x = strtol(buf, &endptr, 10);
if (x == 0) {
memset(kk, 0, sizeof(kk)); // agregar esto
strcpy(kk, (endptr + 1));// agregar esto
strcpy(buf, kk);
}
else {
strcpy(buf, endptr);
}
res+= x;
}
davy.ai
Explicación del problema extraño con las funciones strcpy y strtol en GCC
El código proporcionado anteriormente demuestra un problema extraño encontrado con las funciones de la biblioteca C strcpy y strtol al usar el compilador GCC. El código inicial intenta calcular la suma de enteros incrustados en una cadena, pero produce resultados muy diferentes en dos situaciones de prueba diferentes.
Al investigar, parece que el problema se debe a la función strcpy, que copia una cadena de una ubicación a otra en la memoria. En el código inicial, la línea
strcpy(buf, "a678b")
se utiliza para copiar la cadena “a678b” en el búfer especificado porchar buf[10]
.Sin embargo, esto conduce a un comportamiento indefinido porque la cadena “a678b” consta de caracteres que no son números y el signo negativo. Por lo tanto, cuando se llama posteriormente a la función
strtol
enbuf
, no puede determinar correctamente el valor entero, lo que resulta en una salida incorrecta.Para solucionar este problema, es necesario extraer los valores enteros de la cadena iterando sobre cada caracter individualmente y convirtiendo cualquier subcadena que contenga solo números o signos negativos en un entero utilizando
strtol
.En el código revisado proporcionado, la función
strcpy
se reemplaza por un bucle para extraer cada subcadena que contiene un entero, que luego se convierte en un entero utilizandostrtol
. Si la funciónstrtol
devuelve un valor de 0, esto indica que no hay un entero válido en la subcadena y el bucle avanza al siguiente caracter en la cadena.Sin embargo, por alguna razón, el código revisado todavía produce una salida incorrecta bajo ciertas condiciones de prueba. Para solucionar esto, se agrega un
memset
y unstrcpy
adicionales al bucle siempre questrtol
devuelva 0, lo que inicializa el búferkk
y copia la subcadena que contiene el entero enkk
antes de copiarla enbuf
.En general, el problema con el código inicial surgió al usar
strcpy
para copiar una cadena no válida al búfer, mientras que el código revisado soluciona esto extrayendo subcadenas de enteros válidos utilizando un bucle ystrtol
, y también utilizamemset
ystrcpy
para copiar cualquier subcadena de enteros válidos a un nuevo búfer antes de agregarlos a la salida final.