¿Por qué strtok () se considera inseguro?

¿Qué función (es) de strtok es insegura (en términos de desbordamiento de búfer) que debo tener en cuenta?

Lo que es un poco extraño para mí es que strtok_s (que es “seguro”) en Visual C ++ tiene un parámetro extra de “contexto”, pero parece que es lo mismo en otras formas … ¿es lo mismo o es realmente diferente? ?

    De acuerdo con la sección strtok_s de este documento :

    6.7.3.1 La función strtok_s La función strtok_s corrige dos problemas en la función strtok:

    1. Un nuevo parámetro, s1max, evita que strtok_s se guarde fuera de la cadena que se está tokenizando. (La cadena que se divide en tokens es tanto una entrada como una salida de la función, ya que strtok_s almacena caracteres nulos en la cadena).
    2. Un nuevo parámetro, ptr, elimina el estado interno estático que impide que strtok sea reentrante (Subcláusula 1.1.12). (La función wcstok de ISO / IEC 9899 y la función strtok_r ISO / IEC 9945 (POSIX) corrigen este problema de forma idéntica).

    No hay nada inseguro al respecto. Solo necesita comprender cómo funciona y cómo usarlo. Después de escribir el código y la prueba de la unidad, solo se requieren unos minutos adicionales para volver a ejecutar la prueba de la unidad con valgrind para asegurarse de que está operando dentro de los límites de la memoria. La página man lo dice todo:

    LOCO

    Tenga cuidado al usar estas funciones. Si los usa, tenga en cuenta que:

    • Estas funciones modifican su primer argumento.
    • Estas funciones no se pueden usar en cadenas constantes.
    • La identidad del caracter delimitador se pierde.
    • La strtok() usa un búfer estático durante el análisis, por lo que no es seguro para subprocesos. Usa strtok_r() si esto te importa.

    strtok es seguro en Visual C ++ (pero en ningún otro lugar), ya que utiliza el almacenamiento local de subprocesos para guardar su estado entre llamadas. En cualquier otro lugar, la variable global se usa para guardar el estado strtok ().

    Sin embargo, incluso en VC ++, donde strtok es seguro para subprocesos, sigue siendo un poco extraño: no puedes usar strtok () s en diferentes cadenas en el mismo subproceso al mismo tiempo. Por ejemplo, esto no funcionaría bien:

      token = strtok( string, seps ); while(token) { printf("token=%s\n", token) token2 = strtok(string2, seps); while(token2) { printf("token2=%s", token2); token2 = strtok( NULL, seps ); } token = strtok( NULL, seps ); } 

    La razón por la cual no funcionaría bien, para cada subproceso, solo un estado se puede guardar en el almacenamiento local de subprocesos, y aquí uno necesitaría 2 estados para la primera cadena y para la segunda cadena. Entonces, mientras strtok es seguro para subprocesos con VC ++, no es reentrante.

    Lo que strtok_s (o strtok_r en cualquier otro lugar) proporciona: un estado explícito, y con ese strtok se vuelve a ingresar.

    Si no tiene una cadena terminada correctamente nula; terminarás en un desbordamiento de búfer. También tenga en cuenta (esto es algo que aprendí de la manera difícil) strtok NO parece preocuparse por las cadenas internas. IE que tiene “hello” / “world” analizará “hello” / “world” mientras que “hello / world” se convertirá en “hello world”. Observe que se divide en / e ignora el hecho de que está dentro de un paréntesis.