strlen no verifica NULL

7 minutos de lectura

avatar de usuario
hari

Por que es strlen() no está comprobando NULL?

si lo hago strlen(NULL)los fallos de segmentación del programa.

Tratando de entender la razón detrás de esto (si la hay).

  • Tenga en cuenta que hace aproximadamente 10 años, strlen y otras funciones de cadena verificaban las cadenas nulas antes del procesamiento, pero esto se eliminó porque la mayoría de los programadores verificaron explícitamente estos punteros de todos modos, y no tenía sentido verificarlo dos veces.

    – Búho

    5 de marzo de 2017 a las 16:05

avatar de usuario
Hogan

El razonamiento detrás de esto es simple: ¿cómo puedes verificar la longitud de algo que no existe?

Además, a diferencia de los “lenguajes administrados”, no hay expectativas de que el sistema de tiempo de ejecución maneje datos no válidos o estructuras de datos correctamente. (Este tipo de problema es exactamente la razón por la cual los lenguajes más “modernos” son más populares para aplicaciones que no requieren computación o requieren menos rendimiento).

Una plantilla estándar en c se vería así

 int someStrLen;

 if (someStr != NULL)  // or if (someStr)
    someStrLen = strlen(someStr);
 else
 {
    // handle error.
 }

  • “Administrado”… Así es. Imagina que cada función comienza muy paranoica y verificando todos los posibles errores. Printf almacena metainformación para cada argumento en la lista, cada operación matemática verifica el desbordamiento, etc. Eso está administrado.

    usuario405725

    26 de abril de 2011 a las 20:42

  • Me opongo a la “plantilla estándar”. Si someStr se supone que apunta a una cadena, nunca debe ser un puntero nulo cuando se alcanza este punto en el programa. Algunas personas usan punteros nulos como un valor especial “vacío”, pero esta no es una convención universal y yo diría que hace mucho más daño que bien…

    – R.. GitHub DEJA DE AYUDAR A ICE

    5 de febrero de 2012 a las 1:20

  • @RI supongo que no estamos de acuerdo sobre lo que significa “plantilla estándar”. ¿Tal vez preferirías “patrón útil”? Si te sientes mejor con este término, me parece bien.

    – Hogan

    5 de febrero de 2012 a las 18:44

  • En c11 hay strnlen_s(str, strsz) que devuelve cero si str es un puntero nulo.

    – jfs

    28 de octubre de 2017 a las 13:52

  • @jfs hace más que eso, también limita el tamaño máximo devuelto. Pero tiene un buen punto, esta es claramente la mejor opción para un programa robusto.

    – Hogan

    29 de octubre de 2017 a las 14:08

La parte de la lengua estándar que define la biblioteca de manejo de cadenas establece que, a menos que se especifique lo contrario para la función específica, cualquier argumento de puntero deber tener valores válidos.

La filosofía detrás del diseño de la biblioteca estándar de C es que, en última instancia, el programador está en la mejor posición para saber si realmente es necesario realizar una verificación en tiempo de ejecución. En los días en que la memoria total del sistema se medía en kilobytes, la sobrecarga de realizar una innecesario la verificación del tiempo de ejecución podría ser bastante dolorosa. Entonces, la biblioteca estándar de C no se molesta en hacer ninguna de esas comprobaciones; asume que el programador ya lo ha hecho si es realmente necesario. Si usted saber nunca pasará un valor de puntero incorrecto a strlen (por ejemplo, está pasando un literal de cadena o una matriz asignada localmente), entonces no hay necesidad de saturar el binario resultante con un innecesario verificar contra NULL.

  • +1 para “Si sabe que nunca pasará un valor de puntero incorrecto”.

    – Blagovest Büyükliev

    26 de abril de 2011 a las 21:32

  • “La porción” es C17 7.1.4.1.

    – Ave Milia

    4 de abril de 2021 a las 12:49

avatar de usuario
ninjalj

El estándar no lo requiere, por lo que las implementaciones solo evitan una prueba y, potencialmente, un salto costoso.

Una pequeña macro para ayudar a su dolor:

#define strlens(s) (s==NULL?0:strlen(s))

Tres razones importantes:

  • La biblioteca estándar y el lenguaje C están diseñados asumiendo que el programador sabe lo que está haciendo, por lo que un puntero nulo no se trata como un caso límite, sino como un error del programador que da como resultado un comportamiento indefinido;

  • Incurre en una sobrecarga de tiempo de ejecución: llamar strlen miles de veces y siempre haciendo str != NULL no es razonable a menos que el programador sea tratado como un marica;

  • Se suma al tamaño del código: solo pueden ser unas pocas instrucciones, pero si adopta este principio y lo hace en todas partes, puede inflar su código significativamente.

  • Algunas funciones estándar de C comprueban NULL entradas, por lo que la primera razón es falsa. La tercera razón también es falsa porque poner algunas comprobaciones adicionales en la biblioteca agrega menos al tamaño del código (en una plataforma típica no integrada) que todas las comprobaciones insertadas en el código del cliente.

    – Fred Foo

    26 de abril de 2011 a las 21:02


  • @larsmans: la razón por la que uno no fue una declaración definitiva, sino más bien un intento de describir la mentalidad predominante en la programación en C; razón tres tiene sentido cuando está seguro de que el puntero no puede ser NULL en el código del cliente y tal control actúa más como un assert declaración.

    – Blagovest Büyükliev

    26 de abril de 2011 a las 21:21

  • @larsmans: oh, pero la mayoría de las funciones que verifican NULL están en partes “más nuevas” del estándar (por ejemplo: mb*, wc*), ¿no?

    – ninjalj

    26 de abril de 2011 a las 21:25

  • @ninjalj: Y verificar NULL es en realidad el mayor defecto en las interfaces wc/mb. Una necesidad común con estas funciones es procesar un solo byte/carácter a la vez, y realizar múltiples comprobaciones de puntero nulo inútiles en cada llamada puede fácilmente duplicar el tiempo dedicado a ellas.

    – R.. GitHub DEJA DE AYUDAR A ICE

    5 de febrero de 2012 a las 1:22

  • @R ..: claro, solo estaba señalando que la existencia de esas funciones realmente no constituye un contraejemplo del primer punto de Blagovest.

    – ninjalj

    14 de febrero de 2012 a las 23:52

avatar de usuario
casey flynn

size_t strlen ( const char * str );

http://www.cplusplus.com/reference/clibrary/cstring/strlen/

Strlen toma un puntero a una matriz de caracteres como parámetro, nulo no es un argumento válido para esta función.

  • Algunas funciones estándar de C comprueban NULL entradas, por lo que la primera razón es falsa. La tercera razón también es falsa porque poner algunas comprobaciones adicionales en la biblioteca agrega menos al tamaño del código (en una plataforma típica no integrada) que todas las comprobaciones insertadas en el código del cliente.

    – Fred Foo

    26 de abril de 2011 a las 21:02


  • @larsmans: la razón por la que uno no fue una declaración definitiva, sino más bien un intento de describir la mentalidad predominante en la programación en C; razón tres tiene sentido cuando está seguro de que el puntero no puede ser NULL en el código del cliente y tal control actúa más como un assert declaración.

    – Blagovest Büyükliev

    26 de abril de 2011 a las 21:21

  • @larsmans: oh, pero la mayoría de las funciones que verifican NULL están en partes “más nuevas” del estándar (por ejemplo: mb*, wc*), ¿no?

    – ninjalj

    26 de abril de 2011 a las 21:25

  • @ninjalj: Y verificar NULL es en realidad el mayor defecto en las interfaces wc/mb. Una necesidad común con estas funciones es procesar un solo byte/carácter a la vez, y realizar múltiples comprobaciones de puntero nulo inútiles en cada llamada puede fácilmente duplicar el tiempo dedicado a ellas.

    – R.. GitHub DEJA DE AYUDAR A ICE

    5 de febrero de 2012 a las 1:22

  • @R ..: claro, solo estaba señalando que la existencia de esas funciones realmente no constituye un contraejemplo del primer punto de Blagovest.

    – ninjalj

    14 de febrero de 2012 a las 23:52

¿Ha sido útil esta solución?

Esta web utiliza cookies propias y de terceros para su correcto funcionamiento y para fines analíticos y para mostrarte publicidad relacionada con sus preferencias en base a un perfil elaborado a partir de tus hábitos de navegación. Al hacer clic en el botón Aceptar, acepta el uso de estas tecnologías y el procesamiento de tus datos para estos propósitos. Configurar y más información
Privacidad