El lenguaje de programación Cyclone fue concebido como un dialecto seguro del lenguaje C. [ 2 ] Evita por diseño los desbordamientos de búfer y otras vulnerabilidades posibles en los programas C, sin perder la potencia y la conveniencia de C como herramienta para la programación de sistemas . Sus desarrolladores originales ya no le dan soporte, y las herramientas de referencia no son compatibles con plataformas de 64 bits . Los desarrolladores originales mencionan el lenguaje Rust por haber integrado muchas de las mismas ideas que Cyclone. [ 3 ]
El desarrollo de Cyclone comenzó como un proyecto conjunto de Trevor Jim de AT&T Labs Research y el grupo de Greg Morrisett en la Universidad de Cornell en 2001. La versión 1.0 se lanzó el 8 de mayo de 2006. [ 4 ]
Características del idioma
Cyclone intenta evitar algunos de los problemas comunes de C , manteniendo al mismo tiempo su apariencia y rendimiento. Para ello, Cyclone impone las siguientes limitaciones a los programas:
NULLSe insertan comprobaciones para evitar fallos de segmentación.- La aritmética de punteros es limitada.
- Los punteros deben inicializarse antes de su uso (esto se garantiza mediante el análisis de asignación definida ).
- Los punteros colgantes se evitan mediante análisis de región y límites en
free() - Solo se permiten elencos y sindicatos "seguros".
gotoNo se permite el acceso a ámbitos.switchNo se permiten etiquetas en diferentes ámbitos.- Las funciones que devuelven punteros deben ejecutarse
return setjmpylongjmpno cuentan con soporte
Para mantener el conjunto de herramientas al que están acostumbrados los programadores de C, Cyclone proporciona las siguientes extensiones:
- Los punteros "nunca"
NULLno requierenNULLcomprobaciones. - Los punteros "gordos" admiten aritmética de punteros con comprobación de límites en tiempo de ejecución.
- Las regiones cultivables admiten una forma segura de gestión manual de la memoria.
- Recolección de basura para valores asignados en el montón
- Punteros inteligentes , como punteros únicos
- Gestión de memoria basada en regiones
- Las uniones etiquetadas admiten argumentos de tipo variable.
- Las inyecciones ayudan a automatizar el uso de uniones etiquetadas para programadores.
- El polimorfismo reemplaza algunos usos de
void* - Los argumentos variádicos se implementan como punteros gruesos.
- Las excepciones reemplazan algunos usos de
setjmpylongjmp - Espacios de nombres
- Inferencia de tipo
- Coincidencia de patrones
- Plantillas , tipos parametrizados
En general, Cyclone se parece mucho a C, pero debe considerarse un lenguaje similar a C.
Tipos de puntero
Cyclone implementa tres tipos de punteros :
*(el tipo normal)@(elNULLpuntero nunca), y?(el único tipo con aritmética de punteros permitida, punteros "gordos" ).
El propósito de introducir estos nuevos tipos de punteros es evitar problemas comunes al usar punteros. Tomemos como ejemplo una función fooque recibe un puntero a un entero:
int foo ( int * p );Aunque la persona que escribió la función foopodría haber insertado NULLcomprobaciones, supongamos que por razones de rendimiento no lo hizo. Llamar a ella foo(NULL);resultará en un comportamiento indefinido (normalmente, aunque no necesariamente, se enviará una SIGSEGVseñal a la aplicación). Para evitar tales problemas, Cyclone introduce el @tipo de puntero, que nunca puede ser NULL. Por lo tanto, la versión "segura" de foosería:
int foo ( int @ p );Esto le indica al compilador Cyclone que el argumento de foonunca debe ser NULL, evitando el comportamiento indefinido mencionado anteriormente. El simple cambio de *a @evita que el programador tenga que escribir NULLcomprobaciones y que el sistema operativo tenga que interceptar NULLlas desreferenciaciones de punteros. Sin embargo, este límite adicional puede ser un obstáculo considerable para la mayoría de los programadores de C, quienes están acostumbrados a manipular sus punteros directamente con aritmética. Si bien esto es deseable, puede provocar desbordamientos de búfer y otros errores del tipo "desfase de uno". Para evitar esto, el ?tipo de puntero se delimita mediante un límite conocido, el tamaño del array. Aunque esto añade sobrecarga debido a la información adicional almacenada sobre el puntero, mejora la seguridad. Tomemos, por ejemplo, una strlenfunción simple (e ingenua), escrita en C:
int strlen ( const char * s ) { int i = 0 ; if ( ! s ) { return 0 ; } while ( s [ i ] != '\0' ) { i ++ ; } return i ; }Esta función asume que la cadena que se pasa termina en '\0'. Si a este código se le pasara la cadena sin terminar , iteraría más allá del final de la cadena, en memoria no asociada con la cadena. Las funciones que no son de C estándar ANSI, como , buscan solucionar este tipo de problemas.charbuf[6]={'h','e','l','l','o','!'};strlenstrnlen
La versión Cyclone strlenes similar a la versión C:
int strlen ( const char ? s ) { int n = s.size ; if ( ! s ) { return 0 ; } for ( int i = 0 ; i < n ; i ++ , s ++ ) { if ( * s == ' \ 0' ) { return i ; } } return n ; }Aquí, strlense limita a sí mismo por la longitud del array que se le pasa. Cada uno de los tipos de puntero se puede convertir de forma segura a cualquiera de los otros, y ?el compilador convierte automáticamente arrays y cadenas a . (La conversión de ?a *invoca una comprobación de límites , y la conversión de ?a @invoca tanto una NULLcomprobación como una comprobación de límites. La conversión de *a ?no produce ninguna comprobación; el ?puntero resultante tiene un tamaño de 1.)
Análisis de regiones y punteros colgantes
Considere el siguiente código, en C:
char * itoa ( int i ) { char buf [ 20 ]; sprintf ( buf , "%d" , i ); return buf ; }La función itoaasigna un array de caracteres bufen la pila y devuelve un puntero al inicio de buf. Sin embargo, la memoria utilizada en la pila para bufse libera cuando la función regresa, por lo que el valor devuelto no se puede usar de forma segura fuera de la función. Si bien GNU Compiler Collection y otros compiladores advertirán sobre este tipo de código, el siguiente código generalmente se compilará sin advertencias:
char * itoa ( int i ) { char buf [ 20 ]; sprintf ( buf , "%d" , i ); char * z = buf ; return z ; }GNU Compiler Collection puede producir advertencias para dicho código como efecto secundario de la opción -O2o -O3, pero no hay garantías de que se detecten todos esos errores. Cyclone realiza un análisis regional de cada segmento de código, evitando punteros colgantes, como el que devuelve esta versión de itoa. Todas las variables locales en un ámbito dado se consideran parte de la misma región, separada del montón o cualquier otra región local. Por lo tanto, al analizar itoa, el compilador Cyclone vería que zes un puntero a la pila local y reportaría un error.
Indicadores de grasa
Un puntero gordo se utiliza para permitir la aritmética de punteros. Los punteros gordos deben declararse con @fat. Por ejemplo, argva menudo se declara como tipo char**(un puntero a un puntero a un carácter), o alternativamente se piensa como char*[](puntero a una matriz de caracteres). En Cyclone, esto se expresa como char*@fat*@fat(un puntero gordo a un puntero gordo a caracteres).
Cyclone permite ?representar *@fat. Por lo tanto, las dos declaraciones son equivalentes:
int main ( int argc , char ?? argv ); // equivalente a la declaración más detallada int main ( int argc , char * @ fat * @ fat argv );Tipos parametrizados
Al igual que las plantillas en C++ , Cyclone tiene una forma de programación genérica .
typedef struct LinkedList < ` a > { ` a head ; struct LinkedList < ` a >* next ; } LinkedList < ` a > ;// ... LinkedList < int >* ll = new LinkedList { 1 , new LinkedList { 2 , null }};Se puede utilizar un tipo "abstracto" que encapsule el tipo de implementación, pero que garantice que la definición no se filtre al cliente.
estructura abstracta Cola < ` a > { ListaEnlazada < ` a > frente ; ListaEnlazada < ` a > parte trasera ; };extern struct Cola < ` a > ;Espacios de nombres
En Cyclone existen espacios de nombres , al igual que en C++. Los espacios de nombres se utilizan para evitar conflictos de nombres en el código y siguen la misma ::notación que en C++. Los espacios de nombres pueden anidarse.
espacio de nombres foo { int x ; int f () { return x ; } }espacio de nombres bar { usando foo { int g () { return f (); } }int h () { return foo :: f (); } }Coincidencia de patrones
La coincidencia de patrones se puede realizar en Cyclone de la siguiente manera:
int g ( int a , int b ) { switch ( $ ( a , b - 1 )) { case $ ( 0 , y ) && y > 1 : return 1 ; case $ ( 3 , y ) && f ( x + y ) == 7 : return 2 ; case $ ( 4 , 72 ): return 3 ; default : return 4 ; } }Una letdeclaración se utiliza para hacer coincidir un patrón y una expresión.
typedef struct Pair { int x ; int y ; } Pair ;void f ( Pair p ) { let Pair ( first , second ) = p ; // equivalente a: // int first = px; // int second = py; // ... }Inferencia de tipo
En Cyclone, en lugar de usar autocomo en C y C++ o varen Java y C# , Cyclone usa _(un guion bajo) para denotar una variable de tipo inferido.
_ x = ( SomeType * ) malloc ( sizeof ( SomeType )); // en lugar de: SomeType x = ( SomeType * ) malloc ( sizeof ( SomeType ));_myNumber = 100 ; // se infiere a intExcepciones
Cyclone cuenta con excepciones . Una excepción no capturada detendrá el programa. Al igual que Java, Cyclone cuenta con una excepción de puntero nulo , llamada Null_Exception.
typedef ARCHIVO Archivo ;Archivo * f = fopen ( "/etc/passwd" , "r" ); try { int code = getc (( Archivo * @ notnull ) f ); } catch { case & Null_Exception : printf ( "Error: no se puede abrir /etc/passwd \n " ); return 1 ; case & Invalid_argument ( s ): printf ( "Error: argumento no válido: %s \n " , s ); return 1 ; }También se pueden lanzar excepciones manualmente:
lanzar nueva Null_Exception ( "Esta es una excepción nula" );Véase también
Referencias
- ↑ "Cyclone para programadores de C" . cyclone.thelanguage.org . Consultado el 12 de octubre de 2025 .
- ↑ Jim, Trevor; Morrisett, J. Greg; Grossman, Dan; Hicks, Michael W.; Cheney, James; Wang, Yanling (10 de junio de 2002). "Cyclone: Un dialecto seguro de C" . Actas de la sesión general de la Conferencia Técnica Anual de USENIX . ATEC '02. EE. UU.: Asociación USENIX: 275–288 . ISBN 978-1-880446-00-3.
- ↑ "Ciclón" . cyclone.thelanguage.org . Archivado del original el 21 de mayo de 2006. Consultado el 11 de diciembre de 2023 .
- ↑ "Ciclón" . Universidad de Cornell . Archivado del original el 15 de octubre de 2022. Consultado el 30 de octubre de 2022 .
Enlaces externos
- Página principal de Cyclone
- Sitio web antiguo
- Cyclone - repositorios de código fuente
- Ciclón - Preguntas frecuentes
- Cyclone para programadores de C
- Manual de usuario de Cyclone
- Cyclone: un dialecto de C con tipado seguro, por Dan Grossman, Michael Hicks, Trevor Jim y Greg Morrisett - publicado en enero de 2005
Presentaciones:
- Cyclone: Un dialecto de C con tipado seguro
- Cyclone: Un lenguaje de programación de nivel C seguro para la memoria
- Familia de lenguajes de programación C
- Lenguajes de programación creados en 2002