Las consistencias (e inconsistencias) del C#.

Primero una inconsistencia
O mejor dicho, una supuesta inconsistencia. C# no permite que existan métodos globales, de hecho ni siquiera permite la existencia de variables globales estáticas; A lo más que llega es a permitir miembros estáticos de una clase, sin necesidad de que ésta haya sido instanciada. Personalmente digo: menos mal.


Porque si no, las fichas y las clases deberían tener infinidad de propiedades o métodos compartiendo referencias a otras fichas y otras clases, conformando un maremágnum de elementos cruzados y poseídos entre sí, ofusfcando en gran medida el modelo de objetos.


Pero todo programa (digo ensamblado) ha de tener un punto de entrada, y el C#, violando en cierta manera sus propias reglas, exige la existencia de un elemento global no estático. Ese punto de entrada es main, que debe ser un método miembro estático con una firma concreta.


Técnicamente hablando no estamos violando ninguna regla del C#, pero como es al uso en otros marcos de trabajo, el punto de entrada de la aplicación debería ser una clase heredada de, por poner un ejemplo y sin salirnos mucho de las propias especificaciones del lenguaje, Application.


Que conste que no estoy criticando ni quejándome de esto, pero desde mi punto de vista, que en un lenguaje de programación orientado a objetos tan puro como quiere ser el C#, el punto de entrada de una aplicación sea un método estático global deja un poco que desear.


Y la nueva versión del lenguaje todavía es menos pura (léase LINQ), así que sigo sin entender por qué no permiten ni variables ni métodos globales, máxime cuando la base de LINQ consiste en casi eso (Y en C++/CLI es algo habitual).


Y ahora las consistencias
O mejor dicho, un punto muy fuerte. El último párrafo del capítulo tres del libro The C# Programming Languaje dice (y cito textualmente):



«The ordering of side effects is preserved with respect to volatile reads and writes ($10.4.3). Additionally, the execution environment need not evaluate part of an expression if it can deduce that that expression’s value is not used and that not needed side efects are produced (incluiding any caused by calling a method or accessing a volatile field). When program execution is interrupted by an asynchronous event (such as an exexcption thrown by another thread), it is not guaranteed that the observable side effects are visible in the original program order.»


La última frase del párrafo es evidente por sí misma, y si quieres garantizarlo, utiliza una sección crítica o un bloqueo. Yo me refiero al tema de los efectos laterales en las evaluaciones de las expresiones. En otros lenguajes una vez que se conoce si la expresión es cierta o falsa, no continúa evaluandose.


Al parecer en C#, si el resto de la expresión contiene o pudiera ocasionar algún efecto lateral, ésta se produciría de igual modo. Esta es una característica muy potente a la que no estamos acostumbrados los programadores de sistemas, aunque aunque sí lo estemos en relación al tema de las variables volátiles. Personalmente pienso que disponer de esta característica requiere que se le dé cierto grado de inteligencia al compilador y al entorno de ejecución; ésta sería una ventaja de lo que yo llamo » entorno interpretado».

Pobre y triste preprocesador


Como todo lenguaje de programación que se precie, C# dispone de de un preprocesador para permitir ciertas tareas que no serían posibles (o muy difíciles) sin él. Aunque técnicamente hablando no es un preprocesador, ya que dichas directivas se procesan simultáneamente durante el análisis léxico.


Y el título de esta entrada tiene una explicación: comparado con el de otros lenguajes de programación, el preprocesador de C# es un juguete; eso no quiere decir que no se puedan hacer las mismas cosas que con, por ejemplo, C++, sino que hay que hacerlas de forma diferente.


Definir una constante
Mientras que en otros lenguajes podemos definir una constante y asignarle un valor, o sólo definirla, en C# sólo podemos hacer esto último, con lo que se elimina cualquier posibilidad de sustitución de macros, tokenización, creación de funciones o la simple sustitución de un número mágico por su equivalente predefinida. C# permite que muchas de estas tareas se puedan realizar de forma más segura (y más complicada también) aprovechando que se trata de un lenguaje interpretado (no hay nada nuevo bajo el sol, y el uso del p-code se viene utilizando desde tiempos inmemoriales, quien recuerde el clipper sabrá de que estoy hablando. De hecho, a nivel teórico no existe mucha diferencia entre el basic tradicional y los modernos lenguajes .NET. Estamos hablando de un código fuente que se transforma en una serie de símbolos binarios que un motor de ejecución ha de interpretar).


Compilación condicional
Basadas en las constantes anteriormente citadas se permite lo que se conoce como compilación condicional. Dado que con el preprocesador no se puede asignar un valor a una constante, la compilación condicional sólo puede comprobar la existencia de dicha constante.


La compilación condicional puede llegar a ser enormemente útil en ciertas situaciones; desde diferenciar una construcción de depuración o final, hasta la inclusión de según qué codigo en según qué situaciones.


Un ejemplo que englobe lo visto hasta ahora podría ser el siguiente:



#define HOLA
#if HOLA

#elif ADIOS

#else

#endif
#undef HOLA


Nada más sencillo ni más elemental. Primero definimos la constante HOLA, luego si dicha constante está definida entramos dentro de #if HOLA, si no está definida continuamos la cadena, y en el momento en el que entremos en uno de los if, ya no se siguen evaluando más condicionales, por lo que si estuviera definido tanto HOLA como ADIOS, el compilador no entraría en en bloque ADIOS.


Directivas de diagnóstico
Aunque no suelen ser muy utilizadas en el desarrollo normal (personalmente recomiendo encarecidamente su uso junto a la compilación condicional para evitar situaciones un tanto kafkianas), sí que son enormemente útiles en el mundo de la metaprogramación. Disponemos de dos directivas,



#warning Esto es un aviso
#error Esto es un error.


La primera línea nos imprimirá un aviso como si se tratara de un aviso generado por el compilador, y la segunda un error con las mismas características que los errores del compilador.


Directiva de región
Estas son nuevas en los lenguajes .NET, y se utilizan para agrupar lógicamente bloques de código para simplificar la lectura del mismo. Personalmente las utiliza muy a menudo y me resultan muy utiles para agrupar algoritmos, separar secciones y en general presentar un código mucho más legible y bonito.


Directivas de línea
Quizás las menos utilizadas de todas, y al igual que las de diagnóstico sólo suelen utilizarse en la metaprogramación. Su función, que quizá parezca un tanto sin sentido, es la de cambiar u ocultar los números de línea del fichero de texto, para forzar los que nosotros queramos.



#line 100
#line default
#line hidden


La primera directiva cambia el número de línea por 100, la segunda restaura los números de linea y la tercera los oculta (es decir, si se produce un error o un aviso, esta información aparecerá sin número de línea). La directiva central también sirve para restaurar el estado oculto.


Conclusión
Aunque muy pobrecitas, las funciones del pseudo preprocesador de C# se muestran suficientes, pero por un justo aprobado. Lo que más echo en falta es el poder definir constantes. Ya sé que existe su equivalente dentro de una clase, pero no es lo mismo. A veces son necesarios valores globales a toda la aplicación, lo que obliga a meterlas dentro de una clase, y ya sabemos que el .NET no trabaja muy fino con los elementos estáticos. La verdas es que con el diseño del .NET y del C# se han lucido en algunos aspectos, y este es uno de ellos. En fin.

El uso de la "algarroba" dentro de un programa escrito en C#

Recientemente he comprado en Amazon el libro «THe C# Programming Language» de Hejlsberg y otros, que parece ser es el libro de cabecera del lenguaje de programación C#. Ya casi ni me acordaba, pero la mejor forma de entender un lenguaje de programación es verlo escrito en el formato BNF con pequeños comentarios aclaratorios. Así es como yo aprendí en mis tiempos mozos el lenguaje C, y el C++ no porque el libro de Stroustrup lo explica todo con palabras y ejemplos.


Nada más comenzar con el libro, hay una cosa que me ha llamado enormemente la atención, y es el uso de la arroba en el código fuente. Quizá a quien lea esto, programador avezado en las lides del C#, la resulte obvio y hasta elemental. De hecho, el uso junto a una cadena literal ya lo conocía y suelo utilizarlo muy a menudo.


La arroba delante de un literal cadena
Es sin duda el uso más común, y el más útil de los dos usos que podemos darle a la arroba dentro del código fuente, y se utiliza para interpretar literalmente el contenido de la cadena, es decir, si una cadena tiene una arroba justo antes de las comillas de apertura, la cadena se interpretará literalmente sin prestar atención a códigos de escape, saltos de línea, o cualquier otro símbolo que está contenga y que pudiera hacer protestar al compilador o hacer que éste interpretara de forma especial dichos símbolos. Pongamos un ejemplo sacado del libro:



string a= «Hello t World»;
string b=@»Hello t World»;


Estas dos lineas de codigo harán que las variables contengan (o más bien apunten a un área de la memoria que contenga, ya que son referencias a un objeto):



a -> Hello     World
b -> Hello t World


La forma para un literal cadena literal (valga la redundancia) viene como anillo al dedo para especificar rutas a ficheros sin tener que utilizar los tendente a error códigos de escape, y un uso más avanzado podría ser la creación de código fuente (es decir, tener un programa que genere codigo fuente para hacer otro programa).


La arroba delante de una palabra reservada
Este es el uso que me ha llamado enormemente la atención. Hablando básicamente podemos tener un nombre de variable o cualquier otro elemento dentro de un código fuente que sea una palabra reservada, pero sin serlo. Es decir, el siguiente código fuente es perfectamente válido:



class @class
{
    public static void @static(bool @bool)
    {
        if(@bool)
            System.Console.WriteLine(«true»);
        else
            System.Console.WriteLine(«false»);
    }
}


Este código aparece al final de la página 53 del libro y nos dice que tenemos una clase llamada «class» con un miembro estático llamado «static» que recibe una variable de tipo lógico con el nombre «bool».


Personalmente no encuentro utilidad a esta característica, ni siquiera para metaprogramación, y lo único que hacen es ofuscar el codigo, pero está presente y se puede utilizar.


Más curiosidades
¿Algún programador de C de los de la vieja escuela recuerda los «trigraphs»? Supongo que sí, que no seré yo el único dinosaurio que usaba editores para el codigo fuente que no permitían introducir símbolos especiales. Borland tenía una utilidad para que, una vez escritos dichos trigráficos con un editor normal, fueran traducidos a los símbolos adecuados para que el compilador no protestara. Bueno, pues el C# trae un rico conjunto de su equivalente, pues podemos indicar en cualquier lugar del código fuente (ya sea dentro de una variable, de una palabra reservada, o en cualquier otro lugar), mediante la codificación UNICODE y utilizando la propia nomenclatura de UNICODE, virtualmente cualquier carácter un símbolo que consideremos necesario.

El reconocimiento de voz de Windows Vista SÍ que tiene fallos de seguridad


Me resulta bastante triste confirmarlo, pero el sistema de reconocimiento de voz de Windows Vista tienen varios agujeros de seguridad, alguno de ellos bastante serio.


La siguiente lista resume las cosas que he podido realizar y no deberían haber funcionado:



  • Abrir una consola de comandos y teclear dentro de ella.

  • Borrar todos los documentos del usuario activo.

  • Vaciar la papelera de reciclaje independientemente del número de ventanas abiertas.

  • Borrar correos situados en carpetas estándar de windows mail, como la bandeja de entrada, y luego vaciar la carpeta de elementos eliminados.

  • Ejecutar comandos potencialmente destructivos sin tocar el teclado o el ratón.

  • Redireccionar el navegador web a una dirección que pudiera contener un posible exploit o fallo de seguridad.

  • Pulsar un botón inserto en una página web que, por ejemplo, copiara el código de un script malicioso al portapapeles, primer paso para aprovechar alguno de los otros fallos.

  • Éste no lo he probado, pero creo que se podría ejecutar una consola de comandos con permisos de administrador en aquellos equipos en los que se entrase sin clave de acceso (lo que es habitual en miles de hogares).

  • Este tampoco lo he probado, pero mostrando la rejilla del ratón se puede pulsar en cualquier lado independientemente de la resoución del ordenador.

La solución a todo esto pasa por obligar a que cualquier comando realizado en el navegador, en la consola de comandos, o en el escritorio requiera mantener pulsada una tecla mientras se habla o aceptar el comando mediante la pulsación de una, como en el UAC.

Quit, te necesito. -Ya voy, maiquel y otros menesteres

Originalmente pensé poner el título «-Eres una chica lista, Gay Deceiver. -Eso se lo dirás a todas». Pero entiendo que la referencia quizás no pueda entenderse correctamente ya que, aparte de tratarse de un libro bastante antiguo, hoy en día es casi imposible de encontrar si no es bajándolo de internet. (De todos modos, dejo al sufrido lector que intente adivinar a que novela me estoy refiriendo).


Como ya os habréis imaginado, voy a hablar del sistema de dictado de voz de Windows Vista. Sólo por él, ya vale la pena comprar el nuevo sistema operativo de Microsoft, incluso si es necesario actualizar alguna pieza de tu ordenador. O incluso comprar un equipo nuevo.


Hasta que me llegue la nueva versión retail para mi ordenador principal y de trabajo, he instalado una Home Premium en mi sufrido portátil, aunque sin activar, ya que la versión instalada pertenece a otro ordenador en el que si la he activado. De todos modos, si no me da mucha lata, quizás compre una licencia para éste. Pero aún no lo sé seguro, ya que cuando comience a usar mi equipo principal otra vez para todo, no sé si valdrá la pena gastarme dinero en el portátil.


El sistema de dictado es una gozada, la única forma de verlo bien que va es usarlo, y para usarlo, tienes que pasar por caja, pero te aseguro que vale la pena, sobre todo cuando llevas un rato usándolo y el sistema aprende de ti. Generalmente, cuando se equivoca, si sigues los pasos adecuados para corregir, aprenderá a partir de esa pronunciación difícil y ya no volverá a equivocarse en lo mismo.


Por ejemplo, podrás decir Windonsmai para referir te al windows mail, el sistema de reconocimiento podrá escribir cualquier cosa, le dices que corrija, y la próxima vez que pronuncies windonsmai, será capaz de escribir correctamente Windows Mail. Y todo ello en perfecto castellano.


El supuesto fallo de seguridad.
Las malas lenguas se hacen eco de que el sistema de reconocimiento de voz de Windows Vista presenta un fallo de seguridad garrafal, qué consiste en que una supuesta web pudiera pronunciar una secuencia de frases que el micrófono capturaría y ejecutaría, pudiendo causar algún destrozo en el sistema.
En primer lugar, sería absurdo que alguien se levantara de su asiento sin apagar el micrófono, es decir, no dijera «dajar de escuchar» antes de dejar el ordenador sólo.


En segundo lugar, los comandos de voz no funcionan cuando se intenta algo crítico en el ordenador, como en la pantalla de elevación de privilegios, por lo que aunque se pronunciara la secuencia correcta, sería completamente imposible causar algún destrozo.


No todo es de color de rosa.
Por supuesto no sería yo si no me quejara, pero ahora no me quejo ni de mi ordenador ni de Windows Vista, si no que me quejo de mi mismo.


Y es que cuando me pongo a dictar me pongo nervioso, se me traba a la lengua, y no doy pie con bola. O peor aún: cuando voy a dictar, me quedo en blanco y no sé qué decir. Y es una situación muy grave, porque si no fuera tan nervioso, tardaría mucho menos a dictar que a escribir.


A ver si me acostumbro.


Cambiando un poco de tema, sigo pensando que el windows mail es un juguete, tiene los mismos fallos que la versión anterior, y alguno más. Tengo un grupo de noticias que tiene más de 175000 mensajes y el programa no puede con ellos. El internet explorer también se cae a veces él solo, y el rendimiento en General, al menos en este portátil, es bastante pésimo, pero también lo era con windows xp, así que imagino que en mi ordenador principal (un AMD de 64 bits de doble núcleo y con dos gigabyte de memoria) el rendimiento será más que aceptable, sobre todo si le pongo la versión de 64 bits.


Por cierto, todo esto lo escrito dictando en el bloc de notas.

Windows Mail (ex Outlook Express) no va muy fino en Windows Vista

Tras una tarde, un rato por la noche y casi una mañana usando el Windows Mail casi ininterrumpidamente, he llegado a las siguientes conclusiones generales:



  • Tarda una barbaridad a arrancar, incluso segundas veces.

  • Es muy lento en la carga de carpetas con muchos correos.

  • A veces se queda «pillado», y luego vuelve a responder.

  • La importación de correos desde Outlook Express no es muy fina.

  • Pierde correos, he perdido un árbol de correos de una misma persona que estaba en la bandeja de entrada. (Una inspección de la carpeta correspondiente mostraba que los ficheros .eml estaban en el disco, pero incluso al volverlos a arrastrar al Windows Mail seguían sin aparecer en la lista, pero si los abria a mano sí que se veían. Fue tras importar).

Y las particulares:



  • La tecla de «siguiente mensaje sin leer» en el OE era Ctrl-U, ahora es Ctrl-N, y Ctrl-U es «Nuevo mensaje». ¿Cuándo dejarán de marear cambiando las teclas rápidas en cada versión?

  • Al pulsar Ctrl-N, si ya no quedan sin leer en esa carpeta, te pregunta si quieres avanzar. Le dices que sí y el Ctrl-N deja de funcionar porque el programa pierde el foco, por lo que hay que hacer clic con el ratón en la ventana del mensaje.

  • Debido al fallo anterior, no puedo comprobar si sigue queriendo saltar aun cuando quedan mensajes sin leer en la carpeta actual.

  • Cuando llegas al final de las carpetas, si quedan mensajes sin leer en carpetas susperiores, te dice que no hay mensajes sin leer.

  • En el visor de sucesos hay cientos de errores con algo de que ha excedido los 4 Kb de no se qué.

Aps, y por cierto, hace un rato el ordenador se ha bloqueado y se ha apagado él solo. Tenía abiertos el Windows Mail y dos ventanas del IE, y estaba a desfragmentando con el desfragmentador del Vista. No ha sido una pantalla azul ni un fallo de la batería, ya que el portátil estaba conectado a la red. Y tampoco un sobrecalentamiento. Es la primera vez que me pasa en este cacharro en los dos años que lo tengo.


Como conclusión: El Windows Mail arrastra los mismos bugs que el Outlook Express y encima trae alguno nuevo.

FUD, FUD y más FUD

Para aquel que no lo sepa, FUD es el acrónimo de Fear Uncertainty Doubt en inglés, y es uan expresión que se utiliza cuando alguien dice algo que no es cierto con la intención de causar daño. Pero si a uno le confirman bien confirmado, y encima se asegura por doble partida con referencias de buena mano, pues a veces expresa lo que no tiene que expresar.


1.-Windows Vista
También está de moda ahora en estos blogs emitir una lanza en defensa del nuevo Windows Vista. Hay varios blogs que están emitiendo su defensa, todas ellas a mi modo de ver plenamente justificadas y cabales, así que, pese a parecer el malo de la película, me sumo a las alabanzas.


Recientemente escribí una entrada aquí quejándome de las licencias enormemente restrictivas que Vista va a tener. Realmente continuo ignorando la certeza de si todo lo que dije es cierto o no, pero hay cosas que, vistas con mis ojos y contadas nuevamente por gente desinteresada, no son ciertas.


Lo que puedo afirmar que contradice mis anteriores afirmaciones es:



  • Las versiones OEM se pueden instalar las veces que se quiera sobre el mismo equipo.

  • Si cambias un componente importante en una versión OEM, y vista se niega a activarse, te lo activan con la típica llamada telefónica y sin ponerte pegas.

  • Puedes tener tantas copias instaladas como quieras de el mismo Vista en el mismo ordenador.

Por cierto, tal y como se prometió, el Vista se instala en unos 20 minutos (al menos en un portátil). 


Estoy a la espera de recibir un paquete retail de la Ultimate en inglés, paquete que irá instalado en mi ordenador principal. Intentaré meter tanto la versión de 32 como la de 64, a ver qué pasa. Ya contaré.


2.-Microsoft Live Mail Desktop
También en otra entrada me quejaba amargamente de este software también en fase beta. Curiosamente, y es una cosa que ni por asomo me esperaba, la gente de Microsoft se puso en contacto conmigo para ver si les podía dar más detalles sobre mis problemas con el programa (un consumo de memoria y disco salvajes).


Poca información es la que les pude ofrecer porque lo había desinstalado, pero el contacto siguió, volví a probar otra versión más moderna, y el comportamiento de esta fue bastante mejor.


Y todavía probé una nueva más. Esta funcionó bastante mal, y fue cuando me enteré de que habían retrasado la salida del Live Mail Desktop porque habían detectado ciertos problemas con ciertas configuraciones.


Sin perder el contacto con la gente de Microsoft, y sin dar tampco mucha lata, quiero pensar que mis acciones ayudaron a sacar un producto mejor y más estable.


3.-Bug en Visual Studio 2005SP1
En este blog existe otra entrada más también bastante polémica, y es la del bug con el fondo de la ficha que se corrompe solo… Pues ya no ocurre. Alguna actualización de acá a ahora lo ha solucionado… Esperemos que la de los constructores estáticos y las interrupciones también lo sea pronto.

El pan nuestro de cada día…

… o el padre de todos los bugs (de momento).


Una aclaración (añadido posterior)
Por la serie de comentarios recibidos pudiera parecer que mi aplicativo no está funcionando correctamente, y lo cierto es que tras releer detenidamente la entrada completa me he dado cuenta de que efectivamente así lo parece. Quizás haya pecado de ser demasiado obtuso y/o abstruso a la hora de contar el tema, pero la aplicación YA ESTÁ FUNCIONANDO correctamente sin ningún problema. Diciéndolo en pocas palabras, yo estaba cometiendo un montón de errores en los constructores, errores que generaban excepciones que no se lanzaban donde debían, con el apoteósico final del tema del Orcas. Y todo el comentario viene por eso: parece ser que la máquina virtual .NET no es capaz de lanzar bien las excepciones en esos lugares, y nada más, cosa que al final he terminado confirmando al compilarlo con el Orcas, me ha saltado la excepción que faltaba en el lugar exacto, he visto el fallo cometido por mi, y santas pascuas. 🙂


Y ahora el post original:
Voy a intentar explicar mi última aventura dentro del C++/CLI. Y digo última porque abandono el lenguaje y de momento siempre que pueda haré las cosas en C#, y cuando necesite interop IJW, lo meteré todo en un ensamblado hecho en C++/CLI y lo usaré desde C#. Espero así tener menos problemas, que el IDE se pueda manejar sin que se arrastre mucho, y creo que dejaré de padecer problemas como el que voy a contar ahora. Si el C# fuera tan buggy como el C++/CLI, lo más seguro es que abandone el .NET definitivamente para mis proyectos profesionales, aunque todavía no lo tengo decidido del todo.


La aplicación
Mi último proyecto es una aplicación que irá en un quiosco, completamente autónoma. Aunque no es muy grande, sí que es compleja, pues controla varios dispositivos que yo llamo exóticos (aunque para mí un dispositivo exótico sea un servidor de bases de datos) a través de USB y de canales serie, emplea sockets para conectarse al mundo exterior, y procesa unos 100 megas en elementos gráficos y sonidos.


Este tipo de desarrollos requieren variables globales, pero por desgracia el .NET no las permite, y realmente no entiendo por qué, puesto que tampoco es un entorno Orientado a Objetos puro, y menos aún con las novedades que trae el C# 3.0. Por lo tanto tengo que utilizar clases globales estáticas para realizar el mismo trabajo, pero este tipo de clases tienen una contrapartida, y es que no sabes cuándo se van a instanciar realmente, y en teoría deberían estarlo justo antes de entrar en main, aunque el C++/CLI retarda a veces dicha creación hasta que se llama a cualquier método de la misma, y entonces ejecuta el constructor estático, cosa que para un sistema en tiempo real es inaceptable, por lo que al final lo he tenido que agrupar todo en una clase global que he llamado, ya lo habrán adivinado, Globals. Dentro de esta clase instancio objetos miembro estáticos, que llamo en tiempo de ejecución mediante propiedades:



if(Globals::Devices->InPowerFail) …


Otros detalles de implementación
Una de las cosas que hace la aplicación es consultar periódicamente si tiene actualizaciones para bajárselas e instalarlas, al más puro estilo Windows Update. Todo ese código está en una pareja de ficheros llamada UpgradeEngine.h/UpgradeEngine.cpp. Ahí dentro hay clases para consultar el estado del sistema remoto, para bajarse lo que quiera que tenga que bajarse y para realizar la descompresión y la pertinente instalación, todo ello cuelga de un método global que llamo dentro de main antes de instanciar la ficha principal. La implementación del método global está al final del fichero, y todas las clases por encima de él, y este método global abre un fichero local, mira si le toca y sólo entonces instancia los objetos pertinentes.


Hay muchas más clases que son globales y estáticas, algunas de ellas crean hilos que van a monitorizar los periféricos, que deben estar disponibles lo antes posible para evitar efectos indeseados, otras simplemente precargan parte de los gráficos y de los sonidos, y otras son meros elementos de soporte.


El primer problema
Todos los programadores somos humanos y nos equivocamos. Partiendo de ese principio, y teniendo en cuenta que aproximadamente el 20% de la aplicación está en los constructores globales estáticos, vamos a tener un 20% del total de los bugs en dichos constructores. Y esos bugs, a veces, van a lanzar excepciones, excepciones que deberían ser manejadas primero por un controlador local si lo hubiera y luego por uno global, terminando en todo caso en el de la máquina virtual.


Eso si no hay bugs dentro de esos controladores. Porque si los hay, podría ocurrirte lo que a mi. Haces una pifia, lanzas la aplicación y ¡tachán!, excepción al canto. Bien, en la primera línea del primer método que haya en UpgradeEngine.cpp. Pero si esa clase ni siquiera se está instanciando ahora, y ahí no he tocado nada, y ni siquiera se ha llamado al código que decide si se instancia o no esa clase (recordemos, estamos en un constructor estático global, antes de entrar en main).


Miras el código que has modificado y descubres la pifia, pero te sigue rondando por la cabeza el hecho de que no se haya disparado ahí la excepción. Pero sigues picando código, y vuelves a cagarla. Nueva excepción, que termina en el mismo sitio que antes, excepción generada en otro constructor estático en la otra punta de la aplicación. La cosa ya te mosquea un poco.


Cambias el orden de las clases en UpgradeEngine.cpp, y resulta que las excepciones se siguen capturando en la primera línea del primer método de la primera clase que haya en dicho fichero, se produzcan en el constructor estático que sea. Y entonces empieza a subir la presión sanguínea.


Ya puestos a probar cosas, haces una construcción en release que sabes va a lanzar una excepción en algún lugar, y si ejecutas desde el IDE el comportamiento es el mismo, pero si lanzas la aplicación por sí sola, peta la máquina virtual entera y se cierra todo. No es que te diga que se ha generado la excepción tal o cual, no, sino que lo que se rompe es la máquina virtual completa, el programa nativo que es el propio .NET.


Y entonces decides visitar ese gimnasio que pagas pero que casi nunca usas, y que ahorita mismo te viene al pelo.


El segundo problema
Ya repuesto de lo anterior, estás terminando el aplicativo, sólo te quedan un par de cosas y que te lo revisen y te saquen bugs. Estás contento con el trabajo bien hecho. Te traen el quiosco para que metas tu aplicación en él.


Y comienza el baile de nuevo.


La máquina virtual se cae sola. En tu PC todo va bien, en la placa final ni siquiera obtienes excepciones, sino que la propia VM .NET se cae miserablemente. Bueno, son cosas que pasan. Intentas depurar de forma remota y no puedes porque el ordenador remoto es un XP Home… Los compis que están haciendo la integración en la cadena de montaje también te vienen con pegas, en algunas instalaciones (todas ellas clonadas), la VM salta con excepciones, en otras simplemente se cae. Me traen una que genera casi siempre excepciones y las excepciones tienen el mismo sentido que cuando me pasaba lo que he explicado en el punto anterior, o sea, ninguno. Y de diez máquinas idénticas en pruebas, sólo dos generan excepciones, y las ocho restantes simplemente se caen. Y no son problemas de hardware, porque intercambias componentes y no tienen relación alguna con los fallos…


El intermedio
Hora del kitkat. O de mandarlo todo a tomar por c*l*. Se ha bajado la máquina virtual del Orcas, y tras los problemas con la clave comentados en otro post, me pongo a jugar con él. Una de las pruebas es recompilar mi proyecto C++/CLI actual con este entorno, que por cierto es idéntico al Visual Studio 2005.


Lanzo la aplicación y… y… y… ¡Joder, una excepción en pleno código del UpgradeEngine.cpp! ¡Pero no en la primera línea del primer método de la primera clase, si no en otro sitio! Y hay una traza a un fichero que ni existe ni tiene una ruta válida si no es en mi máquina de desarollo, y ocurre siempre que la máquina NO tenga que actualizar…


¡Alabados sean los chicos-chapuza de Microsoft!


Las preguntas sin resolver
Está claro que el problema estaba en esa línea, pero el asunto no queda lo suficientemente explicado, y aunque en un principio la culpa sea mía por olvidar quitar esa traza, el compilador del Visual Studio 2005 (versión 14.00.50727.762) debería haberse comportado como el del Orcas (versión 15.00.11209).


Otra pregunta sin resolver es por qué no saltaba la excepción en esa línea en mi placa de pruebas (diferente de todas la demás, es una VIA EPOC de esas tiny).


Otra más es por qué en release la máquina virtual .NET se cae entera.


Otra es por qué en ciertas máquinas daba una excepción sin sentido, en otras no y en otras más se caía la VM siendo estas máquinas completamente idénticas.


Más: ¿Por qué cuando hacía una pifia en otro lugar, en lugar de saltar la excepción en ese lugar y con el tipo concreto, saltaba la otra y encima sin sentido alguno?


Posible explicación
Voy a intentar dar una explicación del comportamiento observado, ya que explicar todos los pasos dados antes de compilar la aplicación con el Orcas sería demasiado largo, y encima está el hecho de que al poner trazas interfería en la secuencia, pero creo que mis conclusiones son correctas.


Una aplicación .NET tiene al menos 8 hilos aunque nosotros no creemos ninguno. Supongo que esos hilos están ahí para el recolector de basura, el precompilador, el scheduler de código, el optimizador, el intérprete de la máquina virtual y otros menesteres similares.


Por lo tanto, mientras se está ejecutando código por un lado, seguro que por el otro se está precompilando, optimizando o simplemente realizando otras tareas de mantenimiento, por lo que aunque pensemos en una máquina de von Newman secuencial, realmente no es así (bueno, sí que es así, pero a efectos prácticos no).


Imagino el siguiente escenario: por un lado un hilo está ejecutando los constructores estáticos, y por el otro está preparando el entorno para entrar en main, por un lado se produce una excepción en un constructor estático y por el otro en el código con la traza mal puesta. Entran en acción los manejadores de excepciones, mientras uno busca un manejador, el otro también lo hace, o es entonces cuando mientras una parte de la vm está buscando un manejador la otra ejectua el código que genera una nueva excepción, de forma que se arma la picha un lío y sale por donde puede.


Como en debug hay más código oculto que en release, los tiempos son diferentes, así como las comprobaciones, y dado que la máquina virtual .NET es algo vivo, en determinadas condiciones se produce ciertas secuencias que llevan a su total caída, en otras a salir por donde puede, y finalmente en alguna más a poder lanzar una excepción más o menos válida.


Creo no equivocarme, pero simplemente toda esta explicación podría ser una mera paja mental, así que lo único que puedo afirmar y reafirmar es que


Sigo pensando que hay algo podrido dentro de la máquina virtual .NET

La clave de acceso para el Orcas CTP de enero no funciona (y solución)

Estaba yo más emocionado que una virgen pueblerina el día de su primera boda, esperando pacientemente que se bajaran los tropecientos mil megas de la CTP, tanto, que dejé el ordenador encendido toda la noche porque me faltaba un fichero y ya no podía más con el sueño…


Esta mañana, inocente yo, descomprimo los casi 15 Gigas de máquina virtual (casi nada, espero que esta CTP lleve una espuerta de Gallinfantes de regalo), me pongo al tajo, y ¡oh despiste!, descubro que no anoté la clave que venía por defecto… Bueno, eso tiene solución, vuelvo a la página de descarga y descubro que el usario clave es



Administrator/P2ssword.


Pruebo y joer, no entra. Ni siquiera copiando y pegando el texto en un Virtual PC 2007. Entonces me vino a las mientes otra CTP que no pude probar porque a los chicos de Microsoft se les olvidó que los teclados no americanos tienen algunas letras en otros sitios, ya que, muy c00l ellos, habían puesto una arroba en ella; vamos, para no ser menos y seguir cagándola.


Pues esta vez, armado de mi cabezonería habitual, me he dicho: «aunque tenga que juakear el 2003 Server este, editar a mano el disco duro virtual, reventar a golpes la máquina virtual, por mis O-O, entro y veo el nuevo Orcas.»


Pero al final no ha sido para tanto el asunto, sólo he tenido que buscar un poco por internet, porque como ya es habitual en los chicos pifiosos de Microsoft, la han vuelto a cagar, ya que la clave no es la que viene en la página de descarga, sino:



P2ssw0rd


Vamos, que la ‘o’ es un cero.


Otra cosa pendiente es ver qué hay dentro de esa máquina virtual, pero como decía una pareja de hecho hace unos años, «la próxima semana, hablaremos del gobierno».

Comentarios al "Rationale" de Sutter

Hace unos meses, con la inestimable colaboración de Octavio Hernandez, traduje (tradujimos) el Rationale de Sutter. Fue toda una odisea por lo críptico que escribe ese señor, y por lo críptico del tema en sí. El que todavía no se haya enterado de que puede leer el Rationale en castellano, lo puede obtener de aquí.


Pues bien, este mes, en la MSDN Magazine de Microsoft, Paul DiLascia comenta el Rationale, de hecho lo parafrasea con bastante buen tino y acierto, en muy pocas y entendibles palabras, cubre casi todos los aspectos del documento original.


Si alguien ha intentado leer el Rationale en inglés y se ha hecho la picha un lío por lo difícil, o quizás lo haya intentado con nuestra traducción al castellano con el mismo efecto, ahora puede atisbar su contenido, también en castellano, sin grandes dificultades gracias Paul, que, por desgracia, deja de escribir para la revista.


Lo único achacable al documento es la traducción al castellano, que como comprobará quien la lea, queda un tanto «peculiar».