Cosas mías

January 31, 2007

El pan nuestro de cada día…

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

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

January 30, 2007

VV. AA.:La Batalla del Ebro

Filed under: Lecturas, Historia

A. Besolí, D. Gesalí, X. Hernández, D. Iñigues, J. C. Luque son los autores.

Profusamente ilustrado (tiene dos bloques de láminas), con muchos diagramas de la batalla, el libro cuenta día a día, a veces casi hora a hora, toda la duración de la misma, desde el "desembarco" inicial en la orilla del Ebro por parte del ejército republicano, hasta la destrucción y conquista final por parte del ejército franquista.

Una breve introducción sobre la situación estratégica y sobre personal y armamento, el desarrollo de los combates a lo largo de varias semanas, y una serie de rutas en las que se pueden ver los estragos y los restos que todavía permanecen, unas veces como monumentos.

La verdad es que tanta prolijidad (no sé si existe esa palabra) llega al final a cansar un mucho.

January 29, 2007

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

Filed under: Programació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".

January 26, 2007

Mattew Parker: Monte Cassino

Filed under: Lecturas, Historia

Según dice el autor, la conquista de Monte Cassino es una de los hechos más sangrientos de la Segunda Guerra mundial, causado por la incompetencia manifiesta de los líderes aliados del momento. Yo ni entro ni salgo en ello, pero lo cierto es que el libro resulta bastante pesado de leer por su tamaño y por lo "clásico", todo él narrado en plan descriptivo casi sin entradas "diversificadoras".

Más, en la Wikipedia.

Benito Pérez Galdós EN III-1: Zumalacárregui

Filed under: Lecturas

José Fago es un sacristán de pueblo bastante inquieto e insatisfecho de la sociedad, con dudas trascendentes de todo tipo, y es a través de estos ojos cómo Galdós nos presenta las hazañas de Zumalacárregui, general carlista (del rey Carlos, hermano del recientemente fallecido Fernando), que poco a poco se va haciendo con el norte de España para su causa, frente a los cristinos, la otra facción, liderada por la viuda del rey Fernando, madre de la futura reina Isabel.

Zumalacárregui muere durante la lucha por conquistar Bilbao a causa de una bala perdida, y nuestro personaje casi está con él en sus últimos momentos.

Durante la novela José Fago visita uno y otro lado, recorre el norte de España y nos muestra los hechos acaecidos en ambos bandos, aparte de sus inquietudes personales, entre las que se encuentra un amor de juventud antes de que tomara los hábitos, hija de su amigo Ibarburu, extraño personaje que aparece pero no aparece (ya me entendrá quien la lea o la haya leído).

En esta novela predomina la narración histórica frente a la novelesca, o al menos así lo creo.

January 23, 2007

Comentarios al “Rationale” de Sutter

Filed under: Programación

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".

January 22, 2007

Benito Pérez Galdós: Episodios Nacionales Segunda Serie

El equpaje del Rey José nos cuenta la retirada de Madrid de los franceses con la batalla que se llevó a cabo en las cercanías de Vitoria, humillante final para la conquista francesa de la península. Mientras, se nos narran las aventuras de dos mozos enfrentados por una mujer -y por la ideología política-. Finalmente uno de ellos mata en duelo al otro, y el autor nos deja entrever el ajusticiamiento del asesino.

Memorias de un cortesano de 1815. Sin relación alguna con la trama novelesca anterior, asistimos a la restauración del Rey Fernando… de la boca de uno de sus lacayos, digno ejemplo de personaje prevaricador, oportunista y carente de escrúpulos. El principal de la serie anterior, lo califica de refilón como un pícaro al más puro estilo del Buscón, que lo es pero más. La novela, aparte de mostrarnos una serie de tejemanejes dentro del gobierno real, termina en una divertida secuencia cuando la hija de una de las familias que nuestro personaje ha humillado, se venga de él delante del Rey, con lo que nuestro personaje queda en desgracia de momento.

La segunda casaca. En esta obra aparecen los personajes de la primera novela, mezclados con el lacayo, Salvador Monsalud, ahora convertido en un status algo mayor. Se va viendo cómo los tejemanejes se siguen produciendo con el mismo ritmo, y asistimos a la aparición de las logias masónicas y el movimiento revolucionario.

El Grande Oriente. Continuación inmediata de la anterior, Galdós nos pasea por el interior de las logias masónicas, y lo hace con un tono sardónico en relación a sus ritos. En el tema político asistimos a una revolución liberal semifrustrada -pues se obliga a que el Rey Fernando establezca unas cortes-, a un cambio de bando felizmente llevado por nuestro Salvador y en lo novelesco al abandono de la mujer amada.

El 7 de julio. Asistimos aquí a la fallida revolución absolutista orquestada por el propio rey Fernando, mezclando con las aventuras de Monsalud y de su protegida, y poco más, la verdad. Al final Monsalud se fuga con alguien.

Los cien mil hijos de san Luis. Junto a los amoríos de la Marquesa de Baraona con Monsalud (realmente estos dos personajes son la mujer amada y el matador que aparecen en la primera novela de la serie), Galdós nos narra los hechos finales de la Constitución, con el secuestro del Rey por parte de las Cortes y la huída hacia Andalucía y la caída final en Cádiz, así como la invasión del ejército francés para liberar al Rey Fernando.

El Terror de 1824. Ya en pleno absolutismo, el gobierno se toma la revancha y arrambla con cualquiera que tuviera algo que ver con el período anterior, de hecho Monsalud reside en Inglaterra, y Soledad Gil de la Cuadra se aviene a vivir con Patricio Sarmiento, su vecino que ha perdido el juicio. Pero el gobierno, que no ceja, captura a los dos acusados de conspiradores, así como a sus vecinos los Cordero, que son inocentes. De hecho la única culpable es Soledad, que por los tejemanejes habituales es liberada al fin con los Cordero. A Sarmiento lo ahorcan, en una clara demostración de la arbitrariedad judicial, acusado de ser el principal conspirador; sin embargo, a Seudoquis, que logra escapar, lo dan por perdido. En esta obra Galdós nos muestra el amiguismo, la prevaricación y los más horrendos absurdos que debieron dominar en la época, y que seguro dominan en la nuestra.

Nota especial es el intento de los curas que atienden a Sarmiento por enterarse de más cosas, felizmente cotrarrestado por él mismo, que se confiesa con dios sin intermediario mundano.

Un voluntario realista. La historia comienza en un convento catalán adscrito a un intento de revolución absolutista dentro de un reinado absolutisca, una cosa que sólo puede pasar en España. En él, el sacristán, criado por su abuelo para el puesto, enamorado de ella, se va de guerrillero realista (absolutista), pero las envidias y las luchas de poder lo amargan. Ya de vuelta, enamorado de la monja, quema el convento y la rapta; en otros momentos también ha ayudado a nuestro conocido Monsalud, que ha venido a España desde Inglaterra para ver la situación política y que ha sido preso varias veces. En el golpe fina, el sacristán, Tilín, convencido por la monja raptada, se intercambia por Monsalud y es fusilado en su lugar, huyendo éste a Inglaterra de nuevo.

Los Apostólicos. El rey Fernando agoniza, Monsalud vuelve buscando el perdón y retirarse de la vida política, y finalmente Benigno Cordero le pide a Soledad que se case con él, a lo que ella accede gustosa, pero ciertos papeles faltantes retrasan la boda. Mientras, se van a la finca que Cordero tiene en sus tierras de origen. Una inesperada visita a Soledad de Monsalud en la que también le pide que se case… cuando ya estaba comprometida.

Un faccioso más y algunos frailes menos. El rey definitivamente se muere, se vuelve a armar otra gorda (¿Realmente estaban tan a la greña en aquella época?) y Galdós dice que se acabaron los Episodios Nacionales (luego el éxito editorial y las penurias económicas le obligaron a escribir tres series más). Mientras, en una jugada magistral de Cordero, que ve que Soledad será más feliz con Monsalud que con él, fuerza a que ésta se case, por poderes, mientras Monsalud está en el norte ayudando a su hermano, guerrillero que se vuelve completamente loco.

January 20, 2007

SFF 126-10 (2006) - Analog Science Fiction and Fact, Octubre 2006

Pues eso, continuando con mis lecturas en inglés, he descubierto que es más fácil de lo que en apariencia pensaba y, de hecho, cuando un autor pretende ser culto, emplea muchas palabras latinas con la misma raíz que las equivalentes en castellano y es enormemente fácil de leer…

Este es el primer número de la mítica revista, y ha sido toda una gozada su lectura, ya que es ciencia ficción de la buena ciencia ficción hard. Espero seguir leyendo y comprando los números siguientes en formato electrónico, a unos 3 euros tampoco son tan caros.

Needle with a nametag (Editorial, Stanley Schmidt): Una discusión sobre la tecnología RFID y lo que puede resultar en simplificarnos la vida… y controlarnos mejor.

Rollback (Robert J. Sawyer), I de III: Me ha encantado la ternura y la belleza de esta primera parte. Un matrimonio de ancianos, muy bien avenidos, reciben en su 40 aniversario un regalo inesperado: el SETI ha recibido respuesta al mensaje que enviaron muchos años atrás como respuesta a otro recibido, mensaje que fue decodificado gracias a la mujer del matrimonio (no me acuerdo cómo se llama). Pero ahora son ancianos, y como antes sólo ella es capaz de decodificar el nuevo mensaje, por lo que un patrocinador ofrece al matrimonio la posibilidad de someterse al carísimo tratamiento de rejuvenecimiento que los llevará a ambos de nuevo a los 20 años… Pero un problema en el mismo evita que funcione en la mujer…

The Great Sumatran Easthquakes of 2004-5 (Richard A. Lovett): Articulillo sobre lo ocurrido en el Tsunami y cómo y por qué fallaron las técnicas de detección, amén de todo lo que se ha aprendido de ello y las nuevas tecnologías de detección.

Takes two to tangle (Ben Bova): Space Opera del bueno, rubia espectacular incluída. Cómo intentar viajar instantáneamente, un intento de sabotaje, y un granuja duplicado.

Rival of Mars (David Walton): Otro bello canto a la vida de la mano de la ciencia ficción, aunque aquí el tema no es más que un mero envoltorio y no deja de ser una tierna historia. Ella es madre de alquiler en un futuro en el que las mujeres han estropeado su facultad de crear vida debido al consumo de drogas y otros elementos, y las pocas madres creadoras que quedan son cuidadosamente atendidas. Él, un ingeniero que está en medio del proyecto para poner al hombre en Marte y, cuando le ofrecen un ascenso, su mujer tiene el niño de forma accidentada, lo que le hace replantearse sus prioridades, prefiriendo la vida y el amor al éxito empresarial.

The alternate view: back in time through other dimensions (John G. Cramer): Breve disgresión sobre los últimos avances en física y cosmología teórica que podrían permitir el viaje en el tiempo, tanto hacia adelante como hacia atrás, así como viajar más rápido que la luz. La idea es siempre básicamente la misma: salirte de nuestro continuo y entrar por otro punto, pero ahora hay cierto apoyo matemático y teórico.

In times to come: Un breve avance del mes que viene.

Probability Zero: SETI triumphant (Richard Thieme y Arron Ximm): Una extraña visión de un posible éxito de contacto extraterrestre via el proyecto SETI: no nos llame, la les llamaremos, su tipo de civilización es demasiado común en el universo y estamos muy ocupados, quizás más adelante…

Nigerian scam (Richard A. Lovett): Este está genial, comienza con un ciclista local que tiene que pasar un tiempo a la sombra debido a una caída, y que en su aburrimiento se dedica a la lectura del spam que recibe en su correo. Entre toda la basura lee un extraño mensaje al estilo de la estafa nigeriana. Se trata de unos extraterrestres que han hackeado un servidor de Internet y que desean intercambiar conocimientos… El final es un poco sorprendente, no por el argumento, sino por el golpe de efecto, un pequeño error de interpretación determina en un fallo de escala… bastante humorístico.

From Wyfield, from Malagasy (Robert J. Howe): Este me ha costado un poco más de leer, la prosa es algo difícil por la cantidad de palabras que desconozco, pero ha valido la pena su lectura. Una nave de salvamento se ve envuelta en un accidente y tiene que realizar un aterrizaje de emergencia en un planeta de tipo terrestre pero pretecnológico. De ahí al trato con los nativos, al problema de la comida y a que el hablar un mismo idioma no significa que vayas a comprender a la otra parte… aunque al final resulta que el grupo humano pasa a la madurez.

Sigue una pequeña reseña de Robert J. Howe por Richard A. Lovett, una serie de comentarios a varios libros del género -por cierto, a esos precios sí que compraba yo más cosas en papel-, y a las consabidas cartas al editor.

January 16, 2007

Gregory Benford: A través del mar de soles (Serie Centro Galáctico II)

Estamos en el 2050 y pìco, y la humanidad ha adaptado el asteroide que el propio Nigel fue a investigar para que viaje a través del espacio en busca de un extraño mensaje recibido desde una estrella cercana. Nigel se ha podido manener joven gracias a un proceso de hibernación que a la vez filtra y purifica sus células.

Allí descubren a una extraña raza de seres medio biológicos medio cibernéticos, que viven a duras penas en un asolado planeta controlado por un extraño satélite. Nigel concibe una idea que es rechazada de pleno por la comunidad científica.

Se dirigen a otra estrella y, mientras, en la Tierra, las cosas se ponen feas pues los mares han sido invadidos por unos extraños serea que atacan a todo lo que viaje y/o viva en él.

En un apoteosis final, la humanidad está a punto de ser destruida en la guerra entrablada con esos seres, y el asteroide rocoso, El Lancet, en el que vive Nigel, es atacado por otro de esos extraños satélites que rodean a los planetas que hubieran contenido vida biológica y, al final, la teoría de nuestro personaje se muestra cierta: existe una soterrada guerra entre los seres biológico y los restos cibernéticos evolucionados de antiguas razas, de la que la humanidad ha escapado de milagro.

El libro sirve de reflexión sobre la vida, nuestra forma de destruirnos y de destruir nuestro ecosistema, y lo cuidadosos que hemos de ser a la hora de crear vida artificial. Personalmente pienso que estamos muy, pero que muy lejos de que nuestros ordenadores se nos subleven, sobre todo si sigue dominando Microsoft en el mundo de la informática. :-P

January 13, 2007

Solución a “Obtener el estado de la impresora a través de .NET”, y más bugs (y II)

Filed under: Programación, Lecturas

Visto el éxito obtenido, que nadie ha sido capaz de detectar el bug, ya sea porque no me leen, o porque ya ni se acuerden de Win32, voy a poner aquí la soución al mismo.

También debo dar las gracias a Bartomeu (ver los comentarios a la entrada equivalente al post anerior en mi otro blog, aquí) por haberme hecho notar cierto problema del que no me había dado cuenta; no es que fuera peligroso, pero sí un despiste.

El bug, que clama al cielo, es no liberar la memoria asignada con GlobalAlloc, por lo que cada vez que uno entra en la función, va asignando memoria que nunca llega a liberar. Lo que me hace  notar Bartomeu es que no se necesita ni un solo goto para realizar un código mucho más limpio (cosa que ya había implementado yo en mi propio código), amén de que no debo cerrar el handle si falla la llamada OpenPrinter, ya que no existe ningún manejador válido.

El código definitivo es el siguiente:

bool IsPrinterOk(String ^printerName)
{
    bool bResult=false

;
    HANDLE hPrinter;

    IntPtr pPrinterName=Marshal::StringToHGlobalUni(printerName);

    WCHAR *pChar=(WCHAR *)pPrinterName.ToPointer();

    if(::OpenPrinter(pChar,&hPrinter,NULL)==0)
        return false;

    DWORD bytesNeeded;
    ::GetPrinter(hPrinter,2,0,0,&bytesNeeded);
    PRINTER_INFO_2 *pf=(PRINTER_INFO_2 *)GlobalAlloc(GPTR,bytesNeeded);

    if(::GetPrinter(hPrinter,2,(LPBYTE)pf,bytesNeeded,&bytesNeeded)!=0)
        if(pf->cJobs==0 && pf->Status==0)
            bResult=true;

    GlobalFree(pf);

    ClosePrinter(hPrinter);

    return bResult;
}

Observamos cómo ahora sí que se libera el puntero para albergar a PRINTER_STATUS_2.

Y ahora, más bugs
Es curioso esto del .NET, muy curioso, y conforme va pasando el tiempo le voy teniendo mucho más miedo. En un próximo post lo explicaré, y explicaré el que considero ya el summum de todos los bugs habidos y por haber…

Si recuerdan, en la anterior entrada, la función era estática. Pero si es estática, GlobalFree genera una excepción y tumba la aplicación por completo. No sé a qué pueda deberse, y perfiero no investigarlo.

¿Solución? Definirla como un método normal y corriente. Pero entonces, oh maravilla de todas las maravillas, el compilador me dice que el cuerpo de la función está redefinido. Bien. Si es estática no puedo ponerla en un CPP, si no lo es, tengo que ponerla en uno.

¿Y por qué me dice que el cuerpo de la función está redefinido? El tema es muy sencillo, y realmente podríamos catalogarlo como "feature" más que como bug, pero lo cierto es que el asunto nos da una idea bastante pobre de las interioridades del compilador.

El proceso de parseo de un proyecto C# es sencillo: se parsean todos los ficheros del proyecto uno detrás de otro como si fueran uno solo sobre una misma tabla de símbolos, y luego, en la siguiente pasada se resuelven los símbolos y se pasa todo a código objeto, que el enlazador juntará con poco más.

Esto en C++/CLI no se puede hacer así, ya que violamos el concepto de compilación separada. En C++ primero se parsean las parejas de ficheros cabecera/cuerpos, y luego se juntan y se enlazan. C++/CLI adopta una filosofía intermedia entre C# y el código nativo: primero se compilan las parejas, se juntan todas las tablas de símbolos de todas las parejas, y entonces se vuelven a parsear como si de C# se tratara. Por eso, en otros sitios, he dicho que el código generado con  C++/CLI es de mejor calidad que el de, por ejemplo, C#.

Lo que ocurre es, pues, que se obtiene dos veces un método IsPrinterOk, la primera cuando se parsea su propio fichero y la segunda cuando se junta todo. Y el compilador protesta en lugar de mirar si se trata del mismo código. Y también ese es el motivo por el cual algunos errores y warnings aparecen duplicados en un proyecto, aquellos que sólo se producen en la segunda pasada aparecen una sóla vez, y dos en los que se generan tanto en la primera como en la segunda.

Y eso nos da una ligera idea primero de los esfuerzos y de la complejidad del compilador de C++/CLI, y segundo de que no todo está claro y que el compilador es bastante chapucero.

Get free blog up and running in minutes with Blogsome
Theme designed by Gary Rogers