¿Deben los punteros ser considerados dañinos?

Los punteros apuntan a la estructuración de datos como los gotos al control de flujo.

Puede usar las instrucciones goto para crear esencialmente cualquier control de flujo posible: un bucle do, mientras que un bucle, para un bucle, una declaración de cambio / caso, condiciones en cascada o cualquier otra cosa que pueda imaginar.

Esto significa que una declaración goto es extremadamente versátil; de hecho, es demasiado versátil; El hecho de que se pueda usar un tipo de declaración para crear cualquier posible control de flujo significa que leer la declaración no le dice exactamente nada sobre el tipo de control de flujo que el escritor pretendía crear.

Los punteros son algo similares: puedo usar punteros para crear cualquier estructura de datos posible. El problema también es el mismo: dado que puedo crear cualquier estructura de datos usando un puntero, ver un puntero en el código no me dice exactamente nada sobre qué tipo de estructura de datos se pretendía.

También significa que, así como es bastante fácil crear accidentalmente un bucle infinito con un goto, es posible crear todo tipo de estructuras no deseadas con punteros.

El problema es que si bien hemos estudiado el control de flujo y comprobado que algunas estructuras básicas (la mayoría de las cuales están modeladas bastante bien por los bucles estándar y demás) pueden crear cualquier control de flujo necesario, * no * tenemos tal prueba similar con respecto a las estructuras de datos, es decir, no podemos señalar un conjunto específico de reemplazos más especializados que nos garanticen la capacidad de crear las mismas estructuras de datos.

Como tal, independientemente del grado en que uno quiera deshacerse de los punteros por completo, actualmente no tenemos un reemplazo que garantice que proporcione el mismo conjunto de capacidades (al menos a mi leal saber y entender). La alternativa, por lo tanto, es generalmente crear punteros que admitan solo un subconjunto de las capacidades en (para el ejemplo obvio) punteros en C o C ++, y proponer un nombre diferente para el resultado (y, con fines de marketing, una garantía “no, estos realmente, verdaderamente, definitivamente son * no * punteros”). Sin embargo, eso no cambia el hecho de que el resultado realmente son indicadores. Tampoco cambia el hecho de que admitir un conjunto de funciones más pequeño que el permitido por C y C ++ tampoco es nada nuevo: los punteros Pascales (por un ejemplo obvio) eran mucho más restringidos y no admitían la aritmética en los punteros, pero eran Todavía claramente punteros.

Los punteros pueden ser dañinos, ciertamente. Una herramienta tan poderosa como un puntero puede usarse incorrectamente, y eso es responsabilidad exclusiva del programador. Si uno intenta usar una herramienta que puede causar problemas, es responsabilidad del programador aprender a usarla correctamente. Debido a que parece haber algún obstáculo conceptual que muchos programadores, especialmente aquellos que crecieron (por así decirlo) sin mucha exposición a los métodos de programación de bajo nivel, parecen encontrar dificultades, existe un sentimiento creciente de que el lenguaje de programación C es defectuoso. Sin embargo, hay legiones de programadores para quienes el concepto es completamente cómodo y que comprenden completamente el valor de los punteros. Muchas herramientas utilizadas por los artesanos son dañinas en manos de un usuario no calificado, pero son necesarias para realizar los oficios y oficios de esos artesanos. El uso experto de esas herramientas proporciona una manera de crear de manera segura cosas que no podrían hacerse de otras maneras.
Puede haber muchas formas de programar sin punteros, pero la lista de lugares donde se requieren es algo más larga que el caso único que cita el OP. Si aceptamos que la biblioteca estándar de C ahora es oficialmente parte del lenguaje (una afirmación que adopta el estándar de lenguaje C, AFAIK), entonces no usar punteros haría inutilizables muchas de las funciones de la biblioteca C. Pasar matrices a funciones sería prácticamente imposible, especialmente cuando se desconoce el número de elementos en la matriz en el momento de la compilación. Incluso si el tamaño de las matrices se conociera en el momento de la compilación, y dado que prácticamente todos los compiladores de C usan la pila para pasar parámetros a las funciones, pasar matrices grandes inevitablemente explotaría la pila. Se requiere pasar por referencia en cualquier lugar donde una función necesite modificar datos que están fuera de su alcance de datos locales.
Los punteros pueden apuntar tanto a código como a datos, y sin punteros de función, no veo ninguna manera de lograr un enlace tardío de funciones para cosas como complementos, sistemas de controladores extensibles y similares.
Si el OP sugiere que un gran cuerpo de código de lenguaje C podría reescribirse sin el uso de punteros, diría que no es posible, ciertamente no es práctico. Si el OP sugiere que los punteros podrían eliminarse del lenguaje de programación C, entonces diría que tendría un efecto tan profundo que ya no sería el lenguaje de programación C.

No claro que no. No más que los átomos se pueden considerar dañinos porque pueden convertirse en armas.

Tome las declaraciones GOTO por analogía. Los GoTos no son dañinos, son evitables en programas que pueden estructurarse de manera procesal, por lo que se desarrollaron lenguajes estructurados que los evitaron por completo para desalentar su abuso en forma de código “spaghetti”. Pero, de hecho, son un aspecto particular de una teoría más general de “continuaciones” que de hecho tienen su lugar. (Se les ha llamado “GoTos con argumentos”). Aquí hay un tutorial que encontré haciendo un rápido google en ellos.

Continuaciones hechas simples e ilustradas

Del mismo modo, el ideal de un punto de entrada y de salida exigido por los principios de codificación estructurada temprana resultó innecesario. Realmente no importa para las páginas web como ejemplo, si el codificador incluso usa un GOTO para saltar a una página de error porque el resto del programa será abandonado de todos modos. Pero de todos modos, la idea de los manejadores de errores y los procedimientos de reserva pronto se hizo cargo del código de ejecución del contenedor.

La gestión del puntero puede salirse de control, ser testigo de las bases de datos iniciales de estilo “Red” que se degradaron al infierno cuando se produjeron corrupciones. Las bases de datos relacionales se liberaron de ese paradigma, pero esencialmente la orientación a objetos las usa, incluso si no las ve. Con el aumento de los procesadores rápidos y el mayor uso de la asignación de memoria “dinámica”, las asignaciones de direcciones pueden retrasarse hasta el tiempo de ejecución, lo que permite devoluciones de llamada y todo tipo de beneficios. Java se desarrolló originalmente como un lenguaje de baja huella para aplicaciones integradas y se eliminó de los punteros para fomentar la lógica explícita en la memoria estática. Los apuntadores pueden ocultarse mediante construcciones de programación, pero la manipulación directa de los apuntadores es rápida, es el equivalente a desplegarse en lenguaje ensamblador, mientras se mantiene independiente de la plataforma.

Tiendo a evitarlos, es decir, escribiendo manipulaciones explícitas de punteros, pero cualquier programador que quiera comprender su oficio debe saber dónde se usan y qué están haciendo.

No hay una falta de fiabilidad inherente en los punteros, per se. Funcionan muy bien y funcionan de manera predecible y determinista. El problema surge cuando la gente no comprende las intenciones y usos de ellos, o las políticas en torno a las cosas a las que hacen referencia los punteros.

Entonces: depende.

  1. ¿Qué tan bien entienden los miembros de su equipo los punteros?
  2. ¿Qué tan clara es su política de almacenamiento, copia, retención de referencias a través de llamadas de función, nulos y eliminación?
  3. ¿Qué tipo de punteros estás usando?
  4. ¿Estás en un entorno multiproceso?

Si tiene políticas claras, las personas saben si pueden esconder un puntero, eliminarlo o retenerlo en las llamadas de función.

Cualquier problema con las categorías 1 a 3 anteriores empeora cuando se trata del n. ° 4, subprocesamiento múltiple.

Si su código es tal que no sabe qué puede hacer con el puntero, sugeriría que el puntero no es el problema; La cultura débil de la artesanía de código es.

Del mismo modo, si está en C ++ y usa punteros sin formato en lugar de las referencias más apropiadas y punteros estilo STL, entonces no está haciendo que sus políticas sean claras y seguras.

Si tiene programadores no calificados y / o políticas poco claras (o, Dios no lo quiera), espere muchos errores. Espere que muchos de ellos impliquen el mal uso de punteros.

Finalmente: la obsesión primitiva es dañina. Es triple, por lo que cuando el primitivo que se abusa es punteros. Lo mejor es que el código que trabaja intensamente con punteros se encapsula y administra.

Si va a hacer un lanzamiento ‘considerado dañino’, debe proporcionar una alternativa práctica.

No acepto la premisa de que “todos los demás usos técnicamente no requieren un puntero”.

Para ser claros, no veo una diferencia significativa entre un puntero y decir una referencia de C ++ o una variable de objeto Java. Ambos encapsulan algo que equivale a un puntero.

Incluso si su JVM tiene compactación y su referencia es realmente una clave para una tabla de búsqueda que conduce a la dirección física, no veo cómo eso importa y no veo cómo eso haría que una referencia de objeto no equivalga a ‘un puntero.

Diría que todos los demás usos requieren técnicamente un puntero, pero pueden implicar un poco de azúcar sintáctica y / o algo de control y protección estáticos e incluso en tiempo de ejecución.

Recuerde que no hay nada en los estándares C o C ++ que signifique que no puede proporcionar un compilador que realice comprobaciones de la validez del puntero.

La única razón por la que no lo hacen es porque no hay una demanda suficiente para tales características. Las personas que escriben C y C ++ necesitan (o desean) los punteros de acceso directo tienen que escribir código de alto rendimiento y eso significa que no hay verificación de seguridad.

La mayoría de las aplicaciones no triviales requieren la capacidad de crear algún tipo de variable escribible que identifique algún bloque de datos u objeto en algún nivel de abstracción. También requieren la capacidad de crear dos variables que identifiquen el mismo bloque de datos u objeto de manera que si los datos se modifican por referencia a uno, el otro vea esos cambios.

Puede envolverlo en cintas (o deslizarlo en su calcetín), pero en todas las computadoras que alguna vez lo fueron y (sin algún cambio de paradigma completo) será cuando retire las capas hay una dirección de memoria física (y lo llamaremos un puntero) Todo es cuestión de cuántas cintas quiere, necesita o puede salirse con la suya.

Los punteros no son dañinos. Los punteros no crean errores; los programadores lo hacen. Es como culpar al martillo por golpear un agujero en la pared.

Un puntero es una herramienta para desacoplar a la persona que llama de la persona que llama. Si no los usa, todas las dependencias tendrían que ser dependencias concretas. Los sistemas operativos tendrían que modificarse para vincular a su código.

Como cualquier herramienta, la persona que opera la herramienta debe ser conocedora y experta en el uso de la herramienta.

Descargo de responsabilidad: soy el OP de esta pregunta, y tengo 20 años de experiencia escribiendo C y C ++ (principalmente C). Hace siete años, hice el cambio a Java.

Cuando intenté escribir una biblioteca autorreflexiva para C ++, tenía muchos punteros, especialmente porque tenía que leer los cuadros de la pila y la información del depurador que generó el compilador.

Finalmente comencé a perder la noción de la indirección cuádruple y, utilizando los únicos métodos justificables de mi carrera, aprendí que Java ya era reflexivo. Entonces, aprendí Java, sin dejar de dudar de las excepciones y todo lo demás, incluida la falta de punteros.

En siete años de trabajo con Java, ni una sola vez, recurrí a C ++, porque * HAD * para usar una dirección RAM específica y ninguna otra (también conocido como puntero).

Al trabajar en controladores de dispositivos, en ocasiones, necesito usar los * resultados * de los punteros, aunque alguien más escribe el búfer real (lector / escritor), por lo que tampoco he necesitado un puntero allí. He ido bastante lejos en la pila, codificando como si estuviera haciendo un IAAS seguro.

Los punteros no son dañinos, el mal uso de los punteros es dañino. Nos guste o no, en un nivel fundamental, las CPU funcionan con direcciones, que son los punteros. Si está trabajando con hardware directamente, o está trabajando en el nivel del sistema operativo donde la eficiencia afecta a todas las aplicaciones en la máquina, o está trabajando en un dispositivo integrado donde necesita extraer cada bit de función de una memoria pequeña y un procesador lento, no puede darse el lujo de abstraerse demasiado de la máquina subyacente.

El buen uso de los punteros requiere disciplina cuando la falta de disciplina parecerá más rápida de codificar y funcionará. Terminas pasando más tiempo arreglando los problemas creados por el código descuidado de lo que hubieras dedicado a hacerlo bien la primera vez. En realidad, en la mayoría de los casos, el buen uso del puntero se parece más a referencias de todos modos.

Todos los datos mutables son dañinos, y esto incluye punteros como se conocen tradicionalmente de C.

Es por eso que C ++ y la mayoría de los otros lenguajes tienen referencias (punteros inmutables que deben crearse a partir de algo que existe y que nunca puede cambiar).

Creo que la única razón válida para usar datos mutables es cuando tienes tareas no vinculadas a E / S, lo cual es bastante raro, pero incluso entonces probablemente deberías buscar un compilador inteligente que pueda escribir código que funcione con datos mutables de un descripción que proporciona que no lo hace. Las computadoras son mucho mejores para controlar el desorden que causa la mutabilidad.

Pues claro, pueden ser. Las hojas de sierra también se consideran dañinas si se usan incorrectamente, pero sin ellas no podríamos hacer mucho trabajo ahora, ¿verdad?

Los punteros son lo mismo

Puedes pasar toda tu vida construyendo muebles IKEA y imaginarte un carpintero al igual que puedes programar en JavaScript toda tu vida y llamarte programador. No estoy avergonzando a nadie.

Pero eventualmente te encontrarás con ganas de construir algo que IKEA aún no tiene en su repertorio. Luego deberá utilizar una hoja de sierra / puntero y aceptar todos los peligros que conlleva.

Como regla general, diría ‘no’.

Básicamente, el argumento en contra del uso de punteros se reduce a argumentos para ‘seguridad’ y ‘confiabilidad’.

Puede encontrar un sistema que sea inseguro y poco confiable, que no utilice punteros.

Los punteros son construcciones útiles (esenciales) en C, y C es un lenguaje útil, por lo que los punteros son esenciales si desea usar C. Claro, el uso de ellos puede salir mal, pero puede decirlo sobre cualquier parte de la informática y la programación.

Curiosamente, mientras que Lisp clásico (como se implementó en 1959) se trata de estructuras gráficas basadas en punteros, y su tipo de datos básico (los contras ) es solo un par de punteros adyacentes, el lenguaje en sí no tiene el concepto de punteros. Siempre supuse que esto estaba relacionado con el punto expresado en su pregunta. Los punteros son buenos, dejar que los programadores se burlen de ellos es malo. Cuando cambié a mitad de carrera de Lisp a C ++, descubrí que la manipulación explícita de los punteros hacía que la programación fuera mucho más compleja y propensa a errores de lo necesario.

En ciertos lenguajes, como C (o incluso Asamblea), los punteros son inevitables, por lo que no hace mucha diferencia si son “dañinos” o no.

Los lenguajes más recientes no admiten punteros o no dan razones para que los programadores los usen.

Los punteros son herramientas eléctricas. Al igual que cualquier herramienta eléctrica, las personas que las usan deben tener la habilidad necesaria para usarlas. Si no tienen las habilidades necesarias y no tienen cuidado, entonces son peligrosos.

¿Son dañinos los punteros (en C, supongo)? ¡No!

¿Peligroso? ¡Seguro!

Diría que los punteros son como un núcleo nuclear. Puedes usarlo para construir una bomba destructora de mundos o puedes usarlo para construir una planta de poder que empodera al mundo.

Por supuesto, incluso si elige construir una planta de energía alrededor del núcleo nuclear, si no construye suficientes medidas de seguridad … los resultados podrían ser desastrosos, como en Fukushima.

Los punteros son más o menos como ese núcleo nuclear. Definitivamente peligroso. Dañino solo si no sabes lo que estás haciendo con ellos. Solo mis pensamientos.

¿Es dañina una pistola cargada? Solo si eres propenso a apuntarlo inadvertidamente a tus compañeros de trabajo y también eres propenso a apretar el gatillo inadvertidamente, entonces sí, es dañino.

Lo mismo ocurre con los punteros: son dañinos cuando no se manejan con cuidado.

Los punteros son dañinos SI Y SOLO SI el programador que los usa no los usa correctamente.