{"id":181,"date":"2009-08-02T17:12:48","date_gmt":"2009-08-02T15:12:48","guid":{"rendered":"http:\/\/blog.rastersoft.com\/?p=181"},"modified":"2015-08-15T17:57:54","modified_gmt":"2015-08-15T17:57:54","slug":"vala-de-plata","status":"publish","type":"post","link":"https:\/\/blog.rastersoft.com\/?p=181","title":{"rendered":"Vala de plata"},"content":{"rendered":"<p>Hace un par de meses descubr\u00ed la existencia de<a href=\"http:\/\/live.gnome.org\/Vala\" target=\"_blank\"> Vala, un nuevo lenguaje de programaci\u00f3n<\/a> similar a C# pero con una caracter\u00edstica muy interesante: en lugar de compilar directamente a c\u00f3digo m\u00e1quina o a c\u00f3digo de una m\u00e1quina virtual, compila a c\u00f3digo C, usando GObject para implementar el sistema de clases y objetos. La gran ventaja de\u00a0 esto es que permite crear bibliotecas y clases GObject sin necesidad de lidiar con la complejidad de este sistema, lo que, para los fans de Gnome nos resulta especialmente atractivo. Tambi\u00e9n permite trabajar en un lenguaje moderno, lo suficientemente parecido a C# como para que casi no se note la diferencia, pero sin perder ni un \u00e1pice de rendimiento (lo siento, sigo sin creerme que un <a href=\"http:\/\/en.wikipedia.org\/wiki\/Just-in-time_compilation\">JIT<\/a> consiga siempre mejores rendimientos, fuera de casos patol\u00f3gicos\u00a0 y pruebas de laboratorio).<\/p>\n<p>Otro detalle que me ha parecido fascinante es que simplifica mucho la gesti\u00f3n de memoria. Al contrario de lo que podr\u00eda parecer, no utiliza un recolector de basura como el de Java, sino <a href=\"http:\/\/en.wikipedia.org\/wiki\/Reference_counting\" target=\"_blank\">conteo de referencias<\/a>. Lo interesante es que todo el proceso es muy transparente, pues el propio lenguaje se encarga de utilizarlo casi siempre. As\u00ed, un trozo de c\u00f3digo como \u00e9ste:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">using GLib;\r\n\r\nclass cPrueba:Object {\r\n\r\n}\r\n\r\nint main() {\r\n\r\n    cPrueba miObjeto,miObjeto2;\r\n\r\n    miObjeto=new cPrueba();\r\n    stdout.printf(\"Referencias: %udn\",miObjeto.ref_count);\r\n    miObjeto2=miObjeto;\r\n    stdout.printf(\"Referencias: %ud %udn\",miObjeto.ref_count,miObjeto2.ref_count);\r\n    miObjeto=new cPrueba();\r\n    stdout.printf(\"Referencias: %ud %udn\",miObjeto.ref_count,miObjeto2.ref_count);\r\n    return 0;\r\n}<\/pre>\n<\/div>\n<p>cuando se ejecuta, devuelve la siguiente salida por pantalla:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">Referencias: 1d\r\nReferencias: 2d 2d\r\nReferencias: 1d 1d<\/pre>\n<\/div>\n<p>Vemos que, cuando se hace la primera asignaci\u00f3n, se crea un nuevo objeto de tipo <strong>cPrueba<\/strong> y se asigna a <strong>miObjeto<\/strong>, con lo que su contador de referencias es 1. Luego hacemos la segunda asignaci\u00f3n. Como <strong>miObjeto<\/strong> y <strong>miObjeto2<\/strong> son, realmente, punteros al mismo objeto (y apuntan, por tanto, a la misma zona de memoria), lo \u00fanico que hace Vala es incrementar en uno el contador de referencias; por eso los contadores de referencias de <strong>miObjeto<\/strong> y <strong>miObjeto2<\/strong> valen 2 en la segunda l\u00ednea de la salida: porque en realidad son el mismo objeto, pero est\u00e1 referenciado por dos punteros.<\/p>\n<p>Cuando, finalmente, asignamos un nuevo objeto a <strong>miObjeto<\/strong>, primero Vala libera el objeto al que apunta, lo que en la pr\u00e1ctica consiste en decrementar su contador de referencias. Si en ese momento \u00e9ste pasase a valer cero, entonces ese objeto quedar\u00eda hu\u00e9rfano (ning\u00fan puntero apunta a \u00e9l), por lo que Vala proceder\u00eda a destruirlo autom\u00e1ticamente, liberando su memoria; sin embargo, en este ejemplo eso no ocurre porque <strong>miObjeto2<\/strong> est\u00e1 apuntando al objeto viejo, as\u00ed que lo \u00fanico que ocurre es que su contador de referencias pasa a valer 1. Por su parte, se crea un nuevo objeto de tipo <strong>cPrueba<\/strong>, apuntado por <strong>miObjeto<\/strong>, cuyo contador de referencias tambi\u00e9n vale 1, como vemos en la tercera l\u00ednea de la salida.<\/p>\n<p>Si observamos el c\u00f3digo fuente generado (usando <em>valac -C prueba.vala)<\/em> su funci\u00f3n MAIN queda como:<\/p>\n<div class=\"mycode\">\n<pre class=\"mycode\">gint _main (void) {\r\n    cPrueba* miObjeto;\r\n    cPrueba* miObjeto2;\r\n    cPrueba* _tmp0;\r\n    cPrueba* _tmp2;\r\n    cPrueba* _tmp1;\r\n    cPrueba* _tmp3;\r\n    gint _tmp4;\r\n    miObjeto = NULL;\r\n    miObjeto2 = NULL;\r\n    _tmp0 = NULL;\r\n    miObjeto = (_tmp0 = cprueba_new (), (miObjeto == NULL) ? NULL : (miObjeto = (g_object_unref (miObjeto), NULL)), _tmp0);\r\n    fprintf (stdout, \"Referencias: %udn\", ((GObject*) miObjeto)-&gt;ref_count);\r\n    _tmp2 = NULL;\r\n    _tmp1 = NULL;\r\n    miObjeto2 = (_tmp2 = (_tmp1 = miObjeto, (_tmp1 == NULL) ? NULL : g_object_ref (_tmp1)), (miObjeto2 == NULL) ? NULL : (miObjeto2 = (g_object_unref (miObjeto2), NULL)), _tmp2);\r\n    fprintf (stdout, \"Referencias: %ud %udn\", ((GObject*) miObjeto)-&gt;ref_count, ((GObject*) miObjeto2)-&gt;ref_count);\r\n    _tmp3 = NULL;\r\n    miObjeto = (_tmp3 = cprueba_new (), (miObjeto == NULL) ? NULL : (miObjeto = (g_object_unref (miObjeto), NULL)), _tmp3);\r\n    fprintf (stdout, \"Referencias: %ud %udn\", ((GObject*) miObjeto)-&gt;ref_count, ((GObject*) miObjeto2)-&gt;ref_count);\r\n    return (_tmp4 = 0, (miObjeto == NULL) ? NULL : (miObjeto = (g_object_unref (miObjeto), NULL)), (miObjeto2 == NULL) ? NULL : (miObjeto2 = (g_object_unref (miObjeto2), NULL)), _tmp4);\r\n}<\/pre>\n<\/div>\n<p>(He omitido toda la parte de la definici\u00f3n GObject de la clase ejemplo porque no aporta nada). Vemos en las distintas l\u00edneas como cada vez que se hace una asignaci\u00f3n de un objeto a una variable, primero se procede a liberar lo que hubiese en dicha variable utilizando una llamada a <strong>g_object_unref<\/strong>, para asegurarse de que el contador de referencias decrece correctamente. Luego llama a <strong>g_object_ref<\/strong> con la variable que se copia para incrementar su contador de referencias. Como vemos, este proceso autom\u00e1tico nos simplifica la vida lo suficiente como para que nos podamos olvidar de la gesti\u00f3n autom\u00e1tica de la memoria&#8230;<\/p>\n<p>O casi, porque existe, al menos, un caso en el que no se cumple todo \u00e9sto: las listas. Sin embargo, tras buscar y rebuscar, encontr\u00e9 que es un bug en Vala, as\u00ed que ya est\u00e1 reportado (<a href=\"http:\/\/bugzilla.gnome.org\/show_bug.cgi?id=586577\" target=\"_blank\">http:\/\/bugzilla.gnome.org\/show_bug.cgi?id=586577<\/a>) y deber\u00eda estar corregido en breve, asi que no a\u00f1adais una llamada a unref a mano, sino simplemente esperad a que lo corrijan y recompilad para eliminar el memory leak.<\/p>\n<p>Existe, de todas formas, una opci\u00f3n alternativa, que es utilizar <a href=\"http:\/\/live.gnome.org\/Vala\/GeeSamples\" target=\"_blank\">LibGee<\/a> y su ArrayList. Este tipo de listas no tiene el bug que comento, por lo que, si se utiliza, no hay riesgo de memory leaks.<\/p>\n<p>Pese a todo, es importante se\u00f1alar un par de detalles sobre las listas de Glib en Vala: si vemos la documentacion, hay varias formas de declararlas, en concreto:<\/p>\n<ul>\n<li>var milista = List&lt;contenido_de_lista&gt;();<\/li>\n<li>List&lt;contenido_de_lista&gt; milista = List&lt;contenido_de_lista&gt;();<\/li>\n<li>List milista = List&lt;contenido_de_lista&gt;();<\/li>\n<\/ul>\n<p>Siendo <strong>contenido_de_lista<\/strong> una clase de elementos que contendra la lista. Asi, si quiero hacer una lista de strings la definiria como <strong>List&lt;string&gt;<\/strong>.\u00a0 La cuestion es que, en base a las pruebas que he hecho, solo se realiza gestion de memoria si la lista se define como en la primera o la segunda opcion, porque solo ahi el compilador podra estar seguro de que el contenido es una clase derivada de Object y tiene, por tanto, contador de referencias. Si definimos la lista como en el tercer caso no se realizara gestion de memoria, por lo que podriamos incluso encontrarnos con que metemos en una lista global un elemento definido localmente y que, al terminar la funcion en donde se definio dicho elemento y volver a la funcion principal, dicho elemento es liberado, consiguiendo un hermoso core dump en cuanto intentemos acceder a dicho dato en la lista. Por tanto, mi consejo es utilizar siempre listas bien definidas, salvo que se sepa perfectamente lo que se esta haciendo.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Hace un par de meses descubr\u00ed la existencia de Vala, un nuevo lenguaje de programaci\u00f3n similar a C# pero con una caracter\u00edstica muy interesante: en lugar de compilar directamente a c\u00f3digo m\u00e1quina o a c\u00f3digo de una m\u00e1quina virtual, compila a c\u00f3digo C, usando GObject para implementar el sistema de clases y objetos. La gran &hellip; <a href=\"https:\/\/blog.rastersoft.com\/?p=181\" class=\"more-link\">Seguir leyendo <span class=\"screen-reader-text\">Vala de plata<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,7],"tags":[],"class_list":["post-181","post","type-post","status-publish","format-standard","hentry","category-programacion","category-tutoriales"],"_links":{"self":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/181","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=181"}],"version-history":[{"count":2,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/181\/revisions"}],"predecessor-version":[{"id":1898,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=\/wp\/v2\/posts\/181\/revisions\/1898"}],"wp:attachment":[{"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=181"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=181"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.rastersoft.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=181"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}