es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

¿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;
    }
Tags:  , , ,

Answer

  1. Avatar for 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 por char 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 en buf, 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 utilizando strtol. Si la función strtol 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 un strcpy adicionales al bucle siempre que strtol devuelva 0, lo que inicializa el búfer kk y copia la subcadena que contiene el entero en kk antes de copiarla en buf.

    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 y strtol, y también utiliza memset y strcpy para copiar cualquier subcadena de enteros válidos a un nuevo búfer antes de agregarlos a la salida final.

Comments are closed.