edición general

Intel: "Rust es el futuro de la programación de sistemas, C es el nuevo ensamblador" [ENG]

"Rust addresses the memory management problem in C"

C no tiene ningún problema con la gestión de memoria. Lo que pasa es que C es superpoderoso, te da la herramienta para hacerlo todo. Y con gran poder viene gran responsabilidad. Si luego los programadores son incapaces de devolver la memoria que piden o se pierden con los punteros no es problema del C, es de la capacidad del programador. Si, los programadores son humanos, pero para eso estan los warnings.

Los lenguajes no se han hecho mejores. Unos han limitado sus capacidades para evitar los errores de los programadores, otros se han convertido al equivalente de los bloquecitos de madera de los niños, y otros por el contrario se han convertido en monstruos ininteligibles

Aun diré más. La abstracción con la máquina debería ser mínima. Un programador medio debería ser capaz de programar en ensamblador eficientemente en al menos una arquitectura. Pero lo que estamos haciendo es normalizar la pereza, el descuido y la ignorancia.
#15 Aunque estoy de acuerdo contigo en que el auténtico problema de la gestión de memoria en C está en los despistes del programador, no es menos cierto que al final las rutinas eran muy tediosas de programar: reservar memoria, hacer algo con las variables de tamaño variable, liberar memoria; cuando de eso puede encargarse automáticamente otro algoritmo que hace siempre lo mismo. Pierdes el potencial de gestionar tú mismo la memoria de un modo sencillo (aunque si quieres hacerlo, los lenguajes de alto nivel siempre te proporcionan algún modo de hacerlo), pero a cambio obtienes fiabilidad y menor número de líneas de código para hacer lo mismo. Las ventajas superan tanto los inconvenientes que actualmente es rarísimo de ver un lenguaje que no se comporte así por defecto.
#22 A mí personalmente me parece como comprarse un superdeportivo y limitar la aceleración..
#27 Más bien como hacerte tus propias tuberías o comprarlas pre montadas del leroi merlín. Con las tuyas tienes las medidas exactas, pero tienes que soldarlo todo, un codo mal soldado y tenemos una inundación. Con las de leroy no hay fugas, pero dependes de medidas standard y te tienes que adaptar a lo que leroy tiene.
#27 Casi todos los deportivos nuevos, tienen control de traccion, ABS y ESP y alguno menos Launch control. Ademas tiene corte de inyeccion cuanto te pasas de rpm y los automaticos cambian de marcha solo si te pasas de revoluciones aunque estes en modo manual.

En seguridad hay muchs resctriciones alguna no perjudican nada porque evitan ir por donde no necesitas ir. Algunas son mas intrusivas, pero o en muchos sistemas se procura que si falla una sistema de seguridad haya otro detras o varios e impedir que factor humano pueda crear un problema,.
#22 Ese "eran" de la primera frase se me ha clavao en el alma. :'(

Tienes razón, todos tenéis razón, ya se trata de gustos y filosofías. Yo prefiero tener callos en los dedos de liberar memoria y tener el control, porque de darte cabezazos acabas teniendo un conocimiento avanzado del sistema. Con el otro sistema creamos juniors y seniors, pero no expertos.
#15 Amén. Palabra del senor.
#15 No, lo que estamos haciendo no es normalizar la pereza y el descuido. Lo que estamos haciendo es ser más productivos.

Hace décadas lo caro eran los ordenadores y lo barato los programadores los cuales tenían que afinar sus programas porque los ordenadores no daban más de sí. Ahí un Ensamblador o un C era la apuesta necesaria.

Hoy en día sucede a la inversa, lo barato son los ordenadores y lo caro son los programadores. Como además los ordenadores son órdenes de magnitud más potentes puedes poner capa sobre capa de seguridad para que los ordenadores controlen lo que se está ejecutando liberando tiempo a los programadores para que éstos se centren en lo que deben: funcionalidades y reglas de negocio, no en si se me ha ido un puntero y la he cagado.

Sí estoy deacuerdo contigo en que todo programador debería saber cómo funciona un procesador por dentro, el mítico Motorola 68000 por ejemplo y cómo programarlo con ensamblador para saber qué ocurre por debajo. Pero eso no quita que debamos añadir más capas por encima por seguridad y para aumentar la productividad.

Como curiosidad, hay compañías aéreas cuyos mainframes se programan, todavía hoy, en ensamblador. He visto cosas que no creeríais ;)
#26 Evidentemente estamos cambiando habilidad por potencia y libertad por vigilancia, y el coste es desgraciadamente un factor muy importante. Pero me gustaba la humanidad cuando la habilidad, el esfuerzo y la inteligencia contaban más.
#29 Cuando los hombres eran hombres y se programaban sus propios drivers.
#26 no estoy seguro de que sea un tema solo de productividad, sino de que hay muchos programadores que no saben informática. Saben programar solamente; pero no tienen ni idea ni de lo que es la memoria de intercambio, por poner un ejemplo.

No creo que un buen programador (que sabe de informática) sea mucho más ineficiente en C que en un lenguaje de estos. El problema a veces es que hay programadores que vienen del mundo de los scripts o de las páginas web y cuando ven un puntero les da un síncope.
#36 Ese es otro tema y tienes razón, para que alguien pueda denominarse "desarrollador" o "programador" debería tener conocimiento desde cómo funciona un procesador con sus registros y sus cosas y de ahí hacia arriba en todas las capas, comunicaciones, hilos, sistema operativo. Luego puedes centrarte en una parte pero debes saber que hay un bosque alrededor de tu árbol.
#15 C no es superpoderoso porque C no gestiona la memoria.

Los superpoderosos son los programadores que tienen que lidiar con esas tareas. Y el software desarrollado, que es obviamente rápido.

Los lenguajes son herramientas para desarrollar productos vendibles, usables y seguros. Las mejores herramientas son las que te permiten hacer más trabajo con mayor seguridad en mejor tiempo. Por lo tanto, los lenguajes han ido claramente a mejor.

Lo que tú comentas es más programar por afición. Como quien se construye un coche en un garaje.
#35 C es SUPERpoderoso, porque el programador decide como gestionar la memoria. Otra cosa es que sepa como hacerlo eficientemente...
#46 Hoy en dia se suple tiempo de programacion con hardware mas potente. Se pierde menos tiempo en optimizar y usando L de alto nivel. Es mas barato el hardware que la hora de programador.

Tambien es un problema por supone mas gasto energetico.
cppcms.com/wikipp/en/page/rationale
#80 no en proyectos como el kernel de linux, o embebidos, donde la optimización del código se realiza de forma rutinaria, o en gestión de servidores.

Pero el problema de verdad es que se está perdiendo el contacto con el paradigma. Imagina que seguimos por este camino, y decidimos que no hace falta optimización a bajo nivel. Estaremos siendo ineficientes por diseño, y por tanto dejaremos , eventualmente, proyectos imposibles de Mantener.

Por eso es mejor dejar en cada capa de abstracción, un lenguaje que pueda acceder a todos los recursos de la máquina.

Y por lo menos en la próxima década, la base seguirá siendo Binario>assembly>C. A partir de ahí, ya puede poner el azúcar que quieras, pero de C hacia abajo, es todavía el imperio de las matemáticas y de las estructuras de datos {0x1f609}
#15 this.

C es difícilmente substituible, mayormente porque los sistemas operativos se hacen en C y ensamblador.

Requiere mucha madurez y un profundo conocimiento de la arquitectura de un sistema. Te obliga a saber de estructuras de datos, y en definitiva, a entender como piensa una CPU.

Rust tiene mucho camino por delante, y recomiendo aprender a escribir código en el , porque obliga al programador a usar prácticas seguras, pero hoy por hoy, C va a seguir siendo los cimientos de la computación.

Recuerdo que hace años, se quejaban de que con el lenguaje de moda se podía hacer todo, entonces no tenía sentido aprender un lenguaje anticuado llamado C. Eran los 90, lenguaje era Delphi. El profesor profetizo : en 20 años, nadie usará Delphi, pero seguirán existiendo las listas enlazadas, y se seguirá enseñando C.
Se ha cumplido casi por completo.
#15 C no tiene ningún problema claro, por eso llevamos décadas viendo fallos de segmentación, desbordamientos de buffer y de pila, deadlocks y data races, etc. que con suerte te cuelgan el programa, y sin suerte causan corrupción de datos o fallos de seguridad.

C ya era un lenguaje obsoleto cuando nació, la única razón por la que triunfó fue por la disponibilidad de compiladores gratuitos. A estas alturas merece morir y ser reemplazado por un lenguaje mejor.

Aun diré más. La abstracción con la máquina debería ser mínima. Un programador medio debería ser capaz de programar en ensamblador eficientemente en al menos una arquitectura. Pero lo que estamos haciendo es normalizar la pereza, el descuido y la ignorancia.

Claro que sí guapi. Yo aún diría más, un verdadero programador debería programar sus algoritmos en VHDL y sintetizarlos en una FPGA.
#43 "Yo aún diría más, un verdadero programador debería programar sus algoritmos en VHDL y sintetizarlos en una FPGA."

¿No se hace un ejercicio de eso en la carrera?
#45 Sí, claro que se hace. Yo tuve que implementar un micro RISC de 16 bits.

Que sepas hacerlo no significa que tenga sentido hacerlo, excepto en campos muy concretos. Es como pedirle a cualquier ingeniero que se ponga a resolver un modelo de elementos finitos a mano. Pues no, para eso tenemos software que te lo resuelve mejor que cualquier humano.
#15 En realidad lo has entendido mal. En Rust, estrictamente hablando, no hay gestión de memoria automática, lo que hay es, durante la compilación, una comprobación de que no estás haciendo cosas mal. Todo se hace con un analizador estático de memoria.

Un ejemplo: por defecto, cuando creas un bloque de memoria, ese bloque pertenece a la función que lo creó, y eso significa que si sales de la función, tienes que liberarlo. Pues bien: el analizador estático de Rust, durante la compilación, mira todas las posibles vías de ejecución, y si en alguna te olvidaste de llamar a free(), da un error de compilación. Por supuesto, es legal devolver un bloque de memoria, pero eso sólo mueve la responsabilidad a la función llamante: en ese caso, Rust nunca permitirá que llames a una función que devuelve un bloque de memoria sin asignar dicho bloque a un puntero; y, además, se asegurará de que antes de que la función termine, hayas liberado (o devuelto como valor de retorno) ese bloque. Si no lo haces, error de compilación.

Por supuesto puede ocurrir que pases un puntero a ese bloque de memoria como parámetro de una función: en ese caso la propiedad del bloque pasa a esa función, y ella tiene que, o devolver el bloque al final, o liberarlo ella. Y además, como la función ya no tiene la propiedad del bloque, cualquier uso de ese puntero DESPUÉS de la llamada (que no sea asignar un nuevo bloque, claro) también provocará un error de compilación, porque se supone que la función que recibió ese puntero liberó el bloque. Por supuesto, si la llamada está dentro de un IF, el bloque sólo se liberará si se ejecuta el IF, y eso el compilador lo tiene en cuenta y sigue todas las posibilidades, y sólo si en todos los casos haces lo correcto (liberar la memoria si no se ejecutó el IF, y no tocar el puntero si sí se ejecutó), no dará error de compilación.

Y como este último detalle puede ser un engorro en algunos casos, es posible "prestar" un bloque de memoria a una función; en ese caso la función llamante retiene la propiedad y sigue siendo responsable de liberarlo siempre, por lo que el compilador de Rust lo que se asegurará es que la función que recibe el bloque prestado jamás lo liberará, ni llamará con él a una función que lo libere (esto es, una función que espere recibir la propiedad de un bloque, en lugar de un préstamo).

Si te fijas, son exactamente las reglas que, se supone, hay que seguir en C, pero con la diferencia de que le das la suficiente información al compilador para que él pueda comprobar que las sigues. Es cierto que hay cosas que no provocarían fugas de memoria pero que este esquema no dejaría pasar (por ejemplo, si una función libera un bloque en función de un parámetro externo, y la función llamante lo libera en el caso opuesto), pero precisamente esos casos son los que se deben evitar, pues es fácil que un cambio posterior del código hecho por otra persona que no conoce completamente los entresijos de las funciones haga que surja una fuga de memoria o un dangler pointer (ahora no recuerdo como traducirlo, y no me apetece buscarlo).

Yo hice hace un par de años un proyecto en C y definí, de manera "manual", este mismo esquema: toda función que recibiese un bloque de memoria era responsable de liberarlo. El problema es cuando tienes una función compleja, con muchas posibilidades de bifurcación, y se te pasa liberarlo en una de ellas: por mucho que conozcas la regla, si tienes un error de ese tipo es fácil que ocurra un despiste, y luego ponte a buscar en el código de sopotocientos miles de líneas donde está.

Yo acabé usando un analizador estático para encontrarlo, porque no había manera. Y estaba escondido, estaba...
#54 Muchas gracias por la explicación y el trabajo que te has tomado. No conozco Rust mas allá de un par de tutoriales por curiosidad (y algunas cosas de la sintaxis ya me han dejado aturdido)

Evidentemente, estos lenguajes se desarrollan con el fin de mejorar la calidad del código y aumentar la estabilidad, y sobre todo, la ciberseguridad. La mayoría de las comprobaciones que indicas ya las hace el compilador de C. Las más profundas, como dices, se pueden hacer con un poco de orden y disciplina. Me citas una experiencia puntual. Igual para lo que serviría es para mejorar el procedimiento.

Lo que quiero decir es que no hace falta reinventar la rueda. Evidentemente, las macroempresas como Google o Amazon fomentan lenguajes que aumentan la productividad, porque la pela es la pela. Yo prefiero fomentar la excelencia.

En cualquier caso me refería a la crítica a la gestión de memoria del C, con la que justifican la existencia del lenguaje, no del lenguaje en sí.
#64 Perdona, pero nada de lo que he dicho lo hace el compilador de C en ningún momento: si yo hago un malloc en una función asignando el valor a un puntero, y no hago un free en ninguna parte, el compilador no dice ni mu. Como mucho, te suelta un warning si no asignas un valor devuelto a una variable (y, si no recuerdo mal, sólo con -Wall), pero en ningún momento analiza nada de lo que sí analiza Rust.
#15 Un warning no siempre te va a cantar un memory leak, para ello va siempre bien tener herramientas de análisis de código estático. Por lo demás de acuerdo.
#63 Valgrind rules
#67 Cierto, y Klocwork.

menéame