<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	>

<channel>
	<title>Weblog del rofi</title>
	<atom:link href="http://blog.roger-ferrer.org/feed" rel="self" type="application/rss+xml" />
	<link>http://blog.roger-ferrer.org</link>
	<description>Inquietuds geeks d'un amant dels compiladors i dels llenguatges de programació</description>
	<pubDate>Sun, 22 Mar 2009 17:41:09 +0000</pubDate>
	<generator>http://wordpress.org/?v=2.7.1</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Compiladors creuats o com resoldre el problema de l&#8217;ou i la gallina</title>
		<link>http://blog.roger-ferrer.org/archives/129</link>
		<comments>http://blog.roger-ferrer.org/archives/129#comments</comments>
		<pubDate>Sat, 01 Mar 2008 19:57:01 +0000</pubDate>
		<dc:creator>rofi</dc:creator>
		
		<category><![CDATA[Documentació]]></category>

		<guid isPermaLink="false">http://blog.roger-ferrer.org/archives/129</guid>
		<description><![CDATA[
Un compilador és, en termes molt generals, un programa que converteix d&#8217;algun
llenguatge a un altre (o d&#8217;un codi a un altre). Els més usuals, o més
populars, són els que s&#8217;encarreguen de transformar codi font (escrit en algun
llenguatge de programació) a codi màquina: una codificació de zeros i uns que
un processador (la CPU d&#8217;un ordinador, per [...]]]></description>
			<content:encoded><![CDATA[<p>
Un compilador és, en termes molt generals, un programa que converteix d&#8217;algun
llenguatge a un altre (o d&#8217;un codi a un altre). Els més usuals, o més
populars, són els que s&#8217;encarreguen de transformar codi font (escrit en algun
llenguatge de programació) a codi màquina: una codificació de zeros i uns que
un processador (la CPU d&#8217;un ordinador, per exemple) entén i li fa fer coses.
</p>
<p><span id="more-129"></span></p>
<p>
No vull entrar en detall aquí, però també hi ha d&#8217;altres compiladors que
generen descripcions de baix nivell (a nivell de transistor, per exemple) a
partir de llenguatges de descripció de circuits (a nivell de <q>circuits</q>,
per exemple), compiladors dinàmics de codi màquina d&#8217;un tipus a codi màquina
d&#8217;un altre, etc. No fos cas que ens penséssim que els compilador només escupen
instruccions a partir d&#8217;un llenguatge de programació.
</p>
<p>
Tornant als compiladors més habituals mencionats al primer paràgraf, cal
indicar que normalment s&#8217;executen en mode <em>natiu</em>. Això vol dir que el
compilador s&#8217;executa en el mateix entorn on s&#8217;executarà el programa que està
generant. Això sembla obvi quan estem desenvolupant una aplicació i estem
corregint els possibles problemes que puguin sorgir. Exemples d&#8217;això són els
entorns integrats de desenvolupament a Windows com ara Microsoft Visual
Studio. Res impedeix, però, que el compilador s&#8217;executi en un altre entorn,
diferent al que té com a objectiu (<em>target</em>). Només hem de ser capaços
de poder executar el programa generat a l&#8217;entorn objectiu.
</p>
<p>
Això que a primer moment podria semblar estrany no ho és. Tots els programes
que s&#8217;executen en màquines encastades (<q>empotrades</q>) com ara telèfons
mòbils, càmeres digitals, equips de televisió moderns, etc. s&#8217;acaben
desenvolupant mitjançant aquesta tècnica. L&#8217;eina de desenvolupament del
programador és normalment un PC, llavors per comprovar que tot funciona com
s&#8217;espera aquest utilitza alguna representació, o una versió, de l&#8217;entorn
objectiu. Per a productes nous per als quals no existeix una versió al mercat
se solen usar programes emuladors (per exemple, molta feina es va fer a
l&#8217;emulador del CELL i encara se&#8217;n fa) o en models prototipus (no es estrany
trobar-nos amb gent que executa els programes en una especie de placa
electrònica que poc aspecte té de telèfon mòbil).
</p>
<p>
La qüestió, és que en tots aquests casos el compilador s&#8217;executa en un lloc i
el programa generat en un altre. Quan això passa parlem d&#8217;un compilador
<em>creuat</em>. A vegades la línia que separar un compilador creuat d&#8217;un
natiu és fina. L&#8217;entorn XCode 2.1 de MacOSX permet crear aplicacions PowerPC
(destinades a córrer, per exemple, en un PowerBook G4) o aplicacions Intel
(que corren en un MacBook). Es dóna el cas que a Intel podem executar, gràcies
al suport que té MacOSX, aplicacions PowerPC i Intel. Una cosa similar es dona
en les arquitectures IA32-EMT64 i AMD64 (són quasibé idèntiques i se solen
anomenar col·lectivament com <tt>x86-64</tt>) on podem executar codi de
32-bits de PC (anomenat, entre d&#8217;altres, <tt>x86</tt> o <tt>IA32</tt>) i codi
de 64-bits. En aquests entorns sol estar disponible un compilador capaç de
generar per als dos entorns alhora.
</p>
<p>
El compilador <acronym title="GNU Compiler Collection">GCC</acronym>, el més usat a GNU/Linux, permet la possibilitat de
construir un compilador creuat. De fet, aquest article és una forma de mostrar
les meves frustracions durant aquest procés, que afortunadament he pogut dur a
bon port, després d&#8217;un dia i mig de lluita.
</p>
<p>
Un dels problemes principals alhora de començar algun nou entorn és el
problema de l&#8217;ou i la gallina. Podem entendre el compilador com l&#8217;ou i els
programes (i biblioteques de codi) de la nova plataforma com la gallina, o al
revés si voleu. Resulta que per poder crear els programes del nou entorn ens
cal un compilador. Ara bé, a vegades el compilador requereix parts del nou
entorn, que es generen amb un compilador.
</p>
<p>
Quan volem crear un compilador creuat amb gcc ens hem de plantejar fins a quin
punt volem tornar <q>enrere</q>. Com més enrere tornem, el risc del problema de
l&#8217;ou i la gallina serà major. Què vol dir això? Doncs vol dir que acabarem
trobant-nos com es va trobar la primera persona que va desenvolupar per
aquella plataforma en particular. I això, segurament no és bo.
</p>
<p>
Si volem crear un compilador <tt>gcc</tt> creuat al 100% la recepta de cuina
sembla, però no ho és, senzilla:
</p>
<ol>
<li>Cal crear les eines binàries, <tt>binutils</tt>, per la plataforma
objectiu. Aquí creem eines de molt baix nivell com ara l&#8217;assemblador o
l&#8217;enllaçador (linker).</p>
<li>Cal compilar una primera versió de <tt>gcc</tt> creuat que usarà les eines
binàries del punt anterior. Aquest compilador està a mitges però.</p>
<li>Cal compilar, usant el compilador acabat de crear una primera versió de la
biblioteca del sistema.</p>
<li>Cal compilar, una nova versió del compilador creuat que utilitzi aquesta
biblioteca del sistema. Aquest segon compilador és el que usarem com a creuat.
</ol>
<p>
He omès intencionadament certs detalls. Per començar, el primer compilador
requereix informació de baix nivell de l&#8217;entorn objectiu. Si l&#8217;entorn objectiu
és Linux ens caldran les capçaleres del <tt>kernel</tt> apropiades per
l&#8217;objectiu. Aquesta informació també l&#8217;usarà la biblioteca del sistema,
normalment <tt>glibc</tt> (o alguna altra implementació com ara
<tt>newlib</tt>).
</p>
<p>
Ben mirat tot això sembla <q>fàcil</q> si un sap què ha de fer oi? D&#8217;acord,
anem a provar de fer un compilador creuat per a Itanium.
</p>
<p>
Itanium és la fracassada arquitectura proposada per Intel com a substituta de
IA32, o sigui pretenia ser l&#8217;evolució dels nostres PCs. Fruit d&#8217;un
desenvolupament massa acadèmic, el resultat és una arquitectura
<strong>rara</strong>, on rara vol dir que els que la van dissenyar no se sap
molt bé en què pensaven. Això, juntament al fet que no permetia l&#8217;execució
dels programes IA32 a velocitats decents i que el rendiment pràctic que se li
pot obtenir dista molt del teòric (precisament perquè és una arquitectura
<q>centrada en el compilador</q> i els compiladors fan el que poden), van acabar d&#8217;enfonsar
aquesta arquitectura. Avui dia només sobreviu gràcies a grans servidors de SGI
(amb Linux) i de HP (amb el sistema operatiu HP-UX).
</p>
<p>
Fer un compilador creuat que s&#8217;executi a IA32 i que generi codi Itanium és
quasibé impossible. Almenys des de zero. Per començar, l&#8217;arquitectura defineix
una cosa anomenada <code>unwind</code> i que no es troba implementada dins del
compilador sinó en una biblioteca externa, la biblioteca
<code>libunwind</code>.  El problema és que <code>libunwind</code> requereix
d&#8217;un compilador i una llibreria del sistema per funcionar. En realitat el
problema fins aquí no és tan greu ja que és possible crear un compilador fins
i tot si no es disposa d&#8217;aquesta <tt>libunwind.</tt> Però clar, el que no
podrem és generar cap programa ja que els mancarà la biblioteca.  Si no podem
generar cap programa, ni biblioteca, amb aquest compilador tampoc podrem
compilar la biblioteca del sistema <tt>glibc</tt>. En fi, un bunyol com una
casa.
</p>
<p>
D&#8217;acord, anem a procurar no haver d&#8217;anar tan enrere per evitar aquest
problema. Fem-nos amb els fitxers binaris essencials ja compilats, bàsicament
<code>glibc</code> i <code>libunwind</code>. Podem obtenir aquests fitxers
de versions de Linux ja existents per a l&#8217;arquitectura Itanium, anomenada
IA64 per abreviar. Si fem això és possible saltar-nos tots alguns passos per
crear el compilador: només cal compilar binutils i el compilador creuat
definitiu. Vaig decidir usar els binaris de Debian Testing.
</p>
<p>
Però clar, no tot havia de ser fàcil en aquesta arquitectura recargolada com
és IA64. Pels vols del 2003, els desenvolupadors de <code>gcc</code> i
<code>binutils</code> es van adonar que el codi que generaven no estava
conforme amb les convencions binàries de l&#8217;arquitectura, definides per Intel.
Aquestes convencions s&#8217;anomenen col·lectivament <acronym title="Architecture
Binary Interface">ABI</acronym> i tots els compiladors, per anar bé, s&#8217;han
d&#8217;adherir estrictament a aquesta convenció. Un error pot provocar que els
programes no funcionin bé o, ja de forma més elevada, no puguem mesclar
binaris generats per diferents compiladors (això que sembla terrible era
encara pitjor a Windows on Borland C++ i Microsoft C++ generaven binaris
incompatibles a nivell de fitxers objecte de forma que no era fàcil generar un
únic programa amb parts compilades pels diferents compiladors, afortunadament
al món Linux només s&#8217;usa un contenidor binari anomenat <acronym
title="Executable and Linking Format">ELF</acronym> i això no passa).
</p>
<p>
En qualsevol cas, i de forma molt raonable, el que no podien fer era
incorporar la correcció de forma silenciosa, ja que llavors seria impossible
saber si un binari estava compilat correctament o no. Total que van decidir
afegir una marca als fitxers correctament generats. Resulta que la màquina on
havia d&#8217;executar els programes, una <a
href="http://www.sgi.com/products/servers/altix/4000/">SGI Altix 4700</a>
porta un Linux que tot i reconèixer els fitxers corregits no els suporta.
Total, que vaig perdre 4 hores investigant perquè els meus binaris no
s&#8217;executaven i donaven un error <code>File format not supported</code>, quan
aparentment eren binaris correctes de l&#8217;arquitectura IA64.
</p>
<p>
Cal mencionar que donat que l&#8217;arquitectura IA64 és tan rara és ridículament difícil
trobar binaris per aquesta i tot que hi són trobar les versions antigues és quasi impossible. Cal donar gràcies que existeixi Debian amb suport
IA64 perquè si m&#8217;he de refiar d&#8217;altres distribucions aniria ben servit. Per
sort, els fitxers de Debian Stable sí que són compatibles amb el Linux que hi
havia instal·lat a la màquina Altix: o sigui, eren prou vells.
</p>
<p>
Al final vaig
poder generar un compilador creuat <code>i386->ia64</code>! ueee
<code>:)</code> Només vaig tardar tot un cap de setmana. Un triomf en
productivitat, vaja <tt>xD</tt>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roger-ferrer.org/archives/129/feed</wfw:commentRss>
		</item>
		<item>
		<title>Comptatge de referències</title>
		<link>http://blog.roger-ferrer.org/archives/128</link>
		<comments>http://blog.roger-ferrer.org/archives/128#comments</comments>
		<pubDate>Fri, 03 Aug 2007 13:39:15 +0000</pubDate>
		<dc:creator>rofi</dc:creator>
		
		<category><![CDATA[Documentació]]></category>

		<guid isPermaLink="false">http://blog.roger-ferrer.org/archives/128</guid>
		<description><![CDATA[Un dels problemes principals a l&#8217;hora de desenvolupar aplicacions
en llenguatges «no gestionats» com C o C++ és la gestió de la memòria.

Introducció

Podríem distingir una categoria de llenguatges moderns de propòsit general com
C#, Java o bé tota la família de llenguatges d&#8217;scripting Python, Ruby, Perl i
també els llenguatges funcionals com Haskell, ML, etc.  Tots ells [...]]]></description>
			<content:encoded><![CDATA[<p>Un dels problemes principals a l&#8217;hora de desenvolupar aplicacions
en llenguatges «no gestionats» com C o C++ és la gestió de la memòria.</p>
<p><span id="more-128"></span></p>
<h3>Introducció</h3>
<p>
Podríem distingir una categoria de llenguatges moderns de propòsit general com
C#, Java o bé tota la família de llenguatges d&#8217;scripting Python, Ruby, Perl i
també els llenguatges funcionals com Haskell, ML, etc.  Tots ells es
caracteritzen perquè l&#8217;entorn d&#8217;execució de l&#8217;aplicació ja proporciona
mecanismes automàtics de gestió de memòria. És el que la majoria de la gent
coneix populament com el fet que aquests llenguatges tenen un «garbage
collector».
</p>
<p>
Els problemes amb la gestió de la memòria del programa és doble. Per una banda,
la memòria no deixa de ser un recurs que es pot exhaurir i cal anar alliberant a
mesura que no s&#8217;utilitzi. Quan una aplicació no allibera els recursos de memòria
s&#8217;anonema que té «memory leaks». Els memory leaks no sempre són problemàtics
ja que la majoria de sistemes operatius recuperen tota la memòria gastada per
un programa en el moment que aquest acaba. Si el programa no acaba, o està
designat perquè s&#8217;executi durant molt de temps abans no acabi (per al primer
cas un servidor web com Apache seria un exemple i per al segon un editor com
Eclipse o Emacs, els usuaris són reticents a tancar-los i és d&#8217;esperar que
estiguin molt de temps amb el programa) llavors sí que es converteix en un
problema.
</p>
<p>
L&#8217;altre problema amb la gestió de la memòria és el que podríem anomenar el
problema de les referències compartides. Sovint, i és l&#8217;estratègia de
llenguatges com Java i C#, per no duplicar les entitats que representen la
informació del programa tenim referències a les dades. En comptes de tenir
valors directament, que suposaria anar-los arrossegant (copiant-los) amunt i
avall treballem amb referències a les dades. Per exemple, si treballo amb
objectes que representen persones i necessito un subconjunt d&#8217;aquestes
m&#8217;apuntaré referències a aquestes persones (o sigui, una fletxa que em duu a
cada persona) en comptes de guardar tota la persona en si (copiant tots els
seus atributs d&#8217;informació).
</p>
<p>
En llenguatges no gestionats com C o C++, treballar d&#8217;aquesta manera corre el
risc que no quedi clar quan lliberar el recurs de memòria, ja que les
referències no ens diuen res de l&#8217;ús i el propietari de la dada referenciada.
Així, si alliberem l&#8217;espai associat a un objecte, ens hem d&#8217;assegurar que totes
les referències a aquell objecte ja no s&#8217;utilitzaran. Altrament estarem
sofrint el problema dels «dangling pointers». Addicionalment ens hem d&#8217;assegurar
que no lliberem dos cops un objecte, això s&#8217;anomena «double free».
</p>
<p>
Els llenguatges gestionats, com C# o Java, resolen tots aquests problemes
excepte, possiblement, el del «memory leak». És possible seguir tenint «memory
leaks» en llenguatges gestionats, però això és degut a un control inadequat de
les referències. Per exemple, si tenim objectes «cache» que emmagatzemen
referències a d&#8217;altres objectes, ens hem d&#8217;assegurar que això no causa que
moltíssimes referències que no s&#8217;usaran més queden allà estancades. No fer-ho,
impediria que les dades s&#8217;alliberessin correctament i el consum de memòria
creixeria al llarg del temps.
</p>
<p>
Avui considerarem un cas senzill de gestió de memòria que no es basa en un «garbage
collector» sinó en comptatge de referències.
</p>
<h3>Comptatge de referències</h3>
<p>
Hem mencionat que a C i C++ quan tenim una referència, i això es tradueix el 90% de cops en
<q>tenim un punter a alguna cosa</q>, no sabem res de quantes persones apunten a l&#8217;objecte. Una
solució <em>naïf</em> que funciona per molts casos és un comptador de referències. Aquest
comptador mantindrà el número de referències que hi ha en un moment donat a l&#8217;objecte.
</p>
<p>
El comptatge de referències té avantatges i inconvenients respecte el garbage
collection tradicional.  Com a avantatge cal destacar que el comptatge de
referències es pot anar fent a mesura que s&#8217;executa el programa, això
disminueix els moments en què l&#8217;aplicació queda congelada. Els garbage
collectors més simples senzillament esperen que es consumeixi tota la memòria
prevista i llavors comencen la neteja, això pot suposar interrupcions llargues
en l&#8217;execució. Els garbage collectors més moderns van alliberant progressivament
i utilitzen estratègies sofísticades en forma de «guarderia» on hi tenen els
punters més joves (s&#8217;observa que aquests són els que queden «leakejats» més
aviat).
</p>
</p>
<p>Un inconvenient dels mecanismes basats en comptatge de referències és
que ens cal extendre els objectes amb el comptador. A més, això pot empitjorar
el comportament de la cache ja que certes operacions aparentment tan simples
com assignar un punter en un altre ara impliquen més maquinària. Aquest overhead
és inexistent en sistemes basats en garbage collector.
</p>
<p>
Considerem la següent classe en C++ per a objectes amb comptador de referències.
</p>
<pre>
class ref_countable
{
  private:
    int _refcounter;
  public:
    // Constructor
    ref_countable() : _refcounter(1) { }

    // Destructor, haurà de ser virtual
    virtual ~ref_countable() { }

    // Una referència més a l'objecte
    void object_ref()
    {
      ++_refcounter;
    }

    // Una referència menys a l'objecte
    void object_unref()
    {
      --_refcounter;
      // Si arribem a zero, ens destruïm
      if (_refcounter == 0)
        delete this;
    }

    // La funció dels "fills", es comenta al final
    virtual std::vector&lt;ref_countable**&gt; get_references() = 0;
};

class MyClass : public ref_countable
{
  public:
    MyClass();
    ~MyClass();
    void foo();
};
</pre>
<p>
El que fem és enriquir l&#8217;objecte amb informació de comptatge. Quan es crea un
objecte, només hi ha una referència a ell per part de qui l&#8217;ha creat, per això
el posem a u. Si operem aquest objecte per valor (o com es diu tècnicament amb
«automatic storage»), o sigui com una variable local, funcionarà com sempre.
Però en realitat no volem l&#8217;objecte per valor, sinó que volem manipular
referències a ell. Per això ens caldrà un punter, però no volem un
<tt>MyClass*</tt> sinó alguna cosa més intel·ligent que sàpiga comptabilitzar
bé les referències. La següent és un trosset d&#8217;una classe d&#8217;aquest estil.
</p>
<pre>
// _T ha de ser una classe que heredi de ref_countable
&lt;template typename _T&gt;
class ref_ptr
{
  public:
    // Inicialització a nul
    ref_ptr() : _ref(0) { }

    // Ens apropiem del punter
    explicit ref_ptr(_T* ref)
      : _ref(ref) { }

    // Constructor de copia
    ref_ptr(const ref_ptr&lt;_T&gt;&#038; p)
     : _ref(p._ref)
    {
      if (_ref)
        _ref-&gt;object_ref();
    }

    // Assignació
    ref_ptr operator=(const ref_ptr&lt;_T&gt;&#038; p)
    {
      ref_ptr&lt;T&gt; temp(p);
      // Intercanviem amb una referència temporal
      this-&gt;swap(temp);
      return *this;
    }

    // Rutina d'intercanvi de punters
    void swap(ref_ptr&lt;_T&gt;&#038; p)
    {
      _T *const temp = _ref;
      _ref = p._ref;
      p._ref = temp;
    }

    // Destructor
    ~ref_ptr()
    {
      if (_ref)
        _ref-&gt;object_unref();
    }

    // Per poder usar el ref_ptr&lt;_T&gt; com un
    // punter normal
    _T* operator-&gt;() const
    {
      return _ref;
    }
  private:
    // El punter, pròpiament
    _T* _ref;
};
</pre>
<p>
Ara podem fer coses de l&#8217;estil següent,
</p>
<pre>
ref_ptr&lt;MyClass&gt; f()
{
  ref_ptr&lt;MyClass&gt; pMyClass(new MyClass());
  return pMyClass;
}

void g()
{
    ref_ptr&lt;MyClass&gt; p;

    p = f();

    p-&gt;foo();

    // Aquí s'alliberarà el punter 'p'
}

int main()
{
  g();
}
</pre>
<h3>Problemes</h3>
<p>
Els mecanisme de comptatge de referències funciona bé excepte en un cas. Quan
tenim cicles de punters. Considereu l&#8217;exemple següent.
</p>
<pre>
class B;
class A
{
  private:
    ref_ptr&lt;B&gt; _b;
  public:
    A() { }
    ~A() { }
    setB(ref_ptr&lt;B&gt; b) : _b(b) { }
};

class B
{
  private:
    ref_ptr&lt;A&gt; _a;
  public:
    B() { }
    ~B() { }
    setA(A* a) : _a(a) { }
};

int main()
{
  ref_ptr&lt;A&gt; a(new A());
  ref_ptr&lt;B&gt; b(new B());

  a-&gt;setB(b);
  b-&gt;setA(a);

  // No s'alliberarà cap dels dos
}
</pre>
<p>
Fixeu-vos, just abans d&#8217;acabar <tt>main</tt> tant <tt>a</tt> com <tt>b</tt>
tindra 2 de comptador de referències. En sortir de <tt>main</tt> s&#8217;invocaran
els destructors de <tt>ref_ptr&lt;A&gt;</tt> i <tt>ref_ptr&lt;B&gt;</tt>,
reduint el seu comptador a 1. Com que no és zero cap dels dos s&#8217;alliberarà.  El
problema es troba en que tenim un cicle de brossa.
</p>
<p class="centrat">
<img src="/resources/cicle_referencies.png">
</p>
<h3>Recol·lectar els cicles</h3>
<p>
Com ho podem fer per destruir els cicles? Primer ens hem de mirar les
referències com un graf. Els nodes són els objectes i les referències que tenen
a d&#8217;altres objectes són les arestes. D&#8217;aquí aviat deduïm que un cicle de brossa
que pot ser alliberat forma el que s&#8217;anomena una «component connexa forta».
Això vol dir que des de qualsevol node del cicle de brossa podem arribar a
qualsevol dels altres nodes (sempre hi ha un recorregut entre dos nodes del
cicle de brossa). Una altra propietat molt important dels cicles de brossa és
que no són accessibles des de les referències vives del programa.
</p>
<p>
Un algorisme, proposat per Bacon i Rajan, per resoldre aquest problema adopta
l&#8217;estratègia següent. Tindrem un <q>pool</q> d&#8217;objectes que seran objectes que
potencialment comencen un cicle. L&#8217;estat dels objectes durant la cerca dels
cicles es caracteritzarà per quatre colors. Quan un objecte estigui lliure o en
ús de forma normal el considerarem de color negre. Si l&#8217;objecte ha estat afegit
al pool el considerarem de color lila. Mes avall veurem que ens caldran dos
colors més: el gris i el blanc.
</p>
<p>
Per començar cal deixar clar que si a un objecte li incrementem el comptador
de referències, incondicionalment el marcarem negre, independentment
de si es troba al pool d&#8217;objectes o no. Quan disminuïm el número de referències
d&#8217;un objecte, poden passar dues coses, la primera és que el comptador fos 1
i ara sigui zero. En aquest cas alliberarem l&#8217;objecte de forma normal. Si el comptador
era major que 1 el que farem és marcar l&#8217;objecte de color lila i si no s&#8217;hi trobava,
afegir-lo al pool d&#8217;objectes potencialment arrels d&#8217;un cicle.
</p>
<p class="centrat">
<img src="/resources/marquem_lila.png">
</p>
<p>
Quan el pool superi un llindar d&#8217;objectes potencialment arrels d&#8217;un cicle farem
una recol·lecció. Aquesta recol·lecció té tres fases. En una primera fase
identificarem els objectes «grisos». Aquí intentem identificar quantes
referències són exclusivament degudes a un recorregut iniciat des de dins del
cicle potencial. Ho farem així: per cada objecte que tenim al pool (que sigui
encara de color lila) ens mirarem els seus «fills», o sigui, els objectes a qui
actualment apunta. Si aquests objectes no són de color gris (segurament seran
negres però podrien ser lila, si aquest objecte referenciats també es troba dins
del pool) els disminuirem el comptador de referències i recursivament marcarem en gris
els seus fills. Això el que fa és restar de les referències als objectes, aquelles referències
que tenen origen a objectes potencialment origen de cicles.
</p>
<p class="centrat">
<img src="/resources/marquem_gris.png">
</p>
<p>
Noteu que si durant el marcatge en gris algun comptador de referències esdevé
zero, vol dir que tots els accessos a aquest objecte provenen exclusivament de
nodes que són accessibles des de l&#8217;arrel del cicle en potència. En canvi, si el
comptador d&#8217;un objecte marcat amb gris no és zero vol dir que hi ha algun altre
objecte (que no pertany al cicle) que hi apunta.
</p>
<p>
La següent fase consisteix en marcar de blanc els nodes grisos que tenen comptador
de referència zero. Per cada objecte del pool que és gris ens mirem el seu comptador
de referències. Si és zero marquem l&#8217;objecte com a blanc i tornem a repetir per a
tots els seus fills. Si algun dels fills grisos, o objecte al pool gris, no té comptador
de referències a zero, ara el que fem és remarcar en negre tots els objectes accessibles
des de l&#8217;objecte en qüestió, a mesura que ho fem els incrementarem el seu comptador
de referències.
</p>
<p class="centrat">
<img src="/resources/marquem_blanc.png">
</p>
<p>
Noteu que el procés de remarcat en negre el que ve a fer és actualitzar les
referències degudes a un objecte que encara és referit per algun objecte extern
al cicle. Considereu el cas en què nostre cicle només té un únic element
referenciat des de fora del cicle, això provocaria que tots els objectes, menys
aquest, fossin marcats com a blancs. En fer el remarcat en negre, aquests nodes
veurien correctament incrementat el seu comptador de referències.
</p>
<p>
La tercera fase consisteix en alliberar els objectes que encara romanen de
color blanc (i que el seu comptador de referències és zero). Noteu que per a
C++ eliminar objecte a objecte té conseqüències terrorifiques. En invocar el
destructor de l&#8217;objecte aquest reduirà els comptadors de referències dels
<tt>ref_ptr&lt;T&gt;</tt> que tingui apuntats. Aixo pot provocar problemes de double
free (ja que hem modificat els comptadors de referències reals!), per evitar-ho
hem de ser capaços d&#8217;ignorar aquestes referències (per exemple posant-les a
nul) de forma que el destructor s&#8217;abstindrà de no fer-hi res.
</p>
<p>
Això últim lliga amb el fet que tot i que el mecanisme és força automàtic, en C
i C++ la manca de «consciència» sobre els tipus definits (en llenguatges de programació
es coneix com «reflexivitat») ens obliga a proporcionar una funció que donat un objecte
ens dóni tots els objectes que apunta. En llenguatges com Java o C#, el propi runtime
del llengutge és capaç de coneixer aquests objectes. En aquest cas cal fer-ho manualment.
</p>
<p>
La funció &#8216;fills&#8217; és necessària en qualsevol sistema de gestió automàtica de
memòria, ja sigui basada en comptatge de referències o en sistemes de garbage
collection. Un exemple sofisticat d&#8217;automatitzar la construcció d&#8217;aquesta
funció (per no haver-la d&#8217;escriure un cada cop) és el compilador GCC. Mitjançant
unes marques al propi codi del GCC, una eina és capaç de sintetitzar quines referències
té una classe.
</p>
<h3>Més informació</h3>
<ul>
<li><a href="http://www.gtkmm.org/docs/glibmm-2.4/docs/reference/html/classGlib_1_1RefPtr.html">Glib::RefPtr</a> Un punter intel·ligent
usat a la lliberia <tt>glibmm</tt>. El punter intel·ligent d&#8217;aquest post està basat en aquest.</p>
<li> <a href="http://www.research.ibm.com/people/d/dfb/papers/Bacon01Concurrent.pdf"><q>Concurrent Cycle Collection in Reference Counted Systems</q>, David F. Bacon,
V.T. Rajan in Proceedings European Conference on OOP June 2001, LNCS, vol
2072</a></p>
<li> <a href="http://gcc.gnu.org/onlinedocs/gccint/Type-Information.html#Type-Information">Memory Management and Type Information</a> Aquí explica el mecanisme utilitzat a dins del compilador <a href="http://gcc.gnu.org">GCC</a>
<li><a href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/">A garbage collector for C and C++</a>. Aquest és un garbage collector molt popular utilitzat
en molts projectes de codi open source. És de tipus conservador i treballa analitzant el heap i deduint-ne les referències.
</ul>
]]></content:encoded>
			<wfw:commentRss>http://blog.roger-ferrer.org/archives/128/feed</wfw:commentRss>
		</item>
		<item>
		<title>Ja en van vint-i-cinc</title>
		<link>http://blog.roger-ferrer.org/archives/127</link>
		<comments>http://blog.roger-ferrer.org/archives/127#comments</comments>
		<pubDate>Sun, 29 Apr 2007 08:56:53 +0000</pubDate>
		<dc:creator>rofi</dc:creator>
		
		<category><![CDATA[Penso]]></category>

		<guid isPermaLink="false">http://blog.roger-ferrer.org/archives/127</guid>
		<description><![CDATA[Quantes coses per explicar ara que he fet vint-i-cinc anys. No us penseu que explicaré batalletes, no sóc tan vell (crec).

Donc sí, vaig néixer el dia 27 d&#8217;abril de 1982 o sigui que fa pocs dies vaig fer 25 anys. Vint-i-cinc  anys!!! Això són molts anys!!! T_T. En qualsevol cas no penso lamentar-me de [...]]]></description>
			<content:encoded><![CDATA[<p>Quantes coses per explicar ara que he fet vint-i-cinc anys. No us penseu que explicaré batalletes, no sóc tan vell (crec).<span id="more-127"></span></p>
<p>
Donc sí, vaig néixer el dia 27 d&#8217;abril de 1982 o sigui que fa pocs dies vaig fer 25 anys. <strong>Vint-i-cinc </strong> anys!!! Això són molts anys!!! <tt>T_T</tt>. En qualsevol cas no penso lamentar-me de l&#8217;edat ja m&#8217;arribarà una edat més convenient per queixar-me, no sé, quan en tingui vuitanta o així potser podré queixar-me amb raó <tt>xD</tt>.
</p>
<p>
Vull agrair sobretot als meus bons companys de feina i millor persones que m&#8217;aguanten cada dia. A tots ells i en particular al <a href="http://www.bsc.es/staff.php?p_id=62">Jordi</a>, al <a href="http://www.bsc.es/staff.php?p_id=52">Teru</a>, al <a href="http://www.bsc.es/staff.php?p_id=51">Cid</a>, al <a href="http://www.bsc.es/staff.php?p_id=28">Rodi</a> i al <a href="http://www.bsc.es/staff.php?p_id=49">Jairo</a> els vull donar les gràcies per tot. Als mencionants, agrair-los les dues caixes de <a href="http://es.wikipedia.org/wiki/Ferrero_Rocher">Ferrero Rocher</a>, pel <a href="http://www.flickr.com/photos/rofi/476512456/">Wario Ware Smooth Moves</a> de Nintendo Wii, i per les <a href="http://www.flickr.com/photos/rofi/484823814">tres guardioles</a> (la gallina, la vaca i la marieta&#8230;) que em vau regalar. També vull agrair a l&#8217;Àlex i al Juanjo que em regalessin un <a href="http://www.flickr.com/photos/rofi/476515752">llibre de cuina de l&#8217;Ada Parellada</a> i que no només hi hagués receptes de pastissos <tt>:P</tt>.
</p>
<p>
També vull agrair als companys del <a href="http://www.bsc.es">BSC</a> i del <a href="http://www.ac.upc.edu/">DAC</a> que van venir a celebrar els aniversaris tant del <a href="http://www.bsc.es/staff.php?p_id=56">Jonathan</a>, que també feia 25 anys el mateix dia, i meu.
</p>
<p>També vull agrair-li al <a href="http://kim1367.blogspot.com">KiM</a> que em regalés <a href="http://www.flickr.com/photos/rofi/476507238">la samarreta</a> amb la que triomfaré tots els dies <tt>xDDDD</tt>. Moltes gràcies KiM!
</p>
<p>Gràcies a tots <tt>:)</tt></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roger-ferrer.org/archives/127/feed</wfw:commentRss>
		</item>
		<item>
		<title>Avui va de llibres</title>
		<link>http://blog.roger-ferrer.org/archives/126</link>
		<comments>http://blog.roger-ferrer.org/archives/126#comments</comments>
		<pubDate>Fri, 06 Apr 2007 13:17:39 +0000</pubDate>
		<dc:creator>rofi</dc:creator>
		
		<category><![CDATA[Penso]]></category>

		<guid isPermaLink="false">http://rofi.pinchito.com/weblog/archives/126</guid>
		<description><![CDATA[Amazon és potser una de les poques
empreses que va sobreviure a la bombolla de les punt com del 1997-2001.
El seu model de negoci va aguantar a la sotragada i avui dia és una web que no
només ven llibres, sinó que aplica sofisticats mecanismes de sel·lecció de
continguts per tal de maximitzar les vendes. Jo en sóc [...]]]></description>
			<content:encoded><![CDATA[<p><a href="http://www.amazon.com">Amazon</a> és potser una de les poques
empreses que va sobreviure a la bombolla de les <q>punt com</q> del 1997-2001.
El seu model de negoci va aguantar a la sotragada i avui dia és una web que no
només ven llibres, sinó que aplica sofisticats mecanismes de sel·lecció de
continguts per tal de maximitzar les vendes. Jo en sóc testimoni <tt>:)</tt>
<span id="more-126"></span></p>
<p>
Però no escric aquest <em>post</em> per parlar de Amazon i les seves
increïbles habilitats per fer-me comprar alguna cosa cada cop que hi entro.
Més aviat, avui parlarem d&#8217;una història que m&#8217;ha succeït recentment amb Amazon.
</p>
<p>
<img src="/weblog/resources/pattersson.jpg" style="margin: 4px; float: right" alt="Imatge de Computer Architecture, A Quantitative Approach" title="«Computer Architecture, A quantitative approach» de Hennessy i Patterson">Tot comença el març del 2005, sí, 2005, no és un error. Per aquelles dates
vaig decidir comprar-me un <a
href="http://www.amazon.com/gp/product/1558605967/102-8551424-0875352">llibre</a>
que tot <a href="http://www.coeic.org/ca/">enginyer en informàtica</a> hauria
de tenir al seu prestatge. El llibre és força car ja que no em vaig estar de
res i vaig demanar l&#8217;edició amb tapa dura. Els llibres tècnics, en general, són
força cars i aquest, òbviament, no n&#8217;és una excepció.</p>
<p>
En qualsevol cas, el llibre no va arribar mai. Almenys en el termini
raonable que un dóna als enviaments fets des dels Estats Units. Jo normalment
espero un mes. Segurament l&#8217;enviament des d&#8217;allà, pròpiament dit, deuen ser 2
o 3 setmanes. És el nostre fabulós servei de <a
href="http://www.correos.es">Correus</a> qui afegeix un imprevisible retard
addicional. Coses que té viure en un poble <tt>:)</tt>
</p>
<p>
Cal comentar el <q>problema</q> que pot suposar a vegades encarregar productes
a fora de la Unió Europea. Molts productes, contràriament al que dictarien els
principis de lliure mercat però coherentment amb les idees de protecció dels
mercats propis, tenen aranzels. Això vol dir que, tècnicament, productes
comprats als EUA són susceptibles de pagar aranzels.
</p>
<p>
No puc explicar la raó profunda, algun dia ho esbrinaré, però els enviaments
postals <q>ordinaris</q> per correu aeri no solen suposar aranzels.
L&#8217;explicació més simple sol ser la més correcta. Per tant, assumirem que a
l&#8217;aduana el tràfic de correu és tan exagerat que no estan per <q>tonteries</q>
i només alguns paquets <q>sel·leccionats</q> se&#8217;ls deu aplicar l&#8217;impost
d&#8217;entrada.
</p>
<p>
Continuant amb la història després d&#8217;aquest breu incís, quan va arribar abril
vaig decidir queixar-me a Amazon que no m&#8217;havia arribat el llibre. Molt
amablement Amazon em va respondre que cap problema que me n&#8217;enviaven un altre.
</p>
<p>
Malaguanyat llibre. No va arribar mai tampoc <tt>xD</tt>
</p>
<p>
Ara segurament em titllareu, pel cap baix, de <q>tonto</q> si us dic que
davant de la maledicció del llibre en qüestió, un servidor va decidir
abandonar aquest enviament. Ras i curt, vaig llençar els diners d&#8217;aquesta
comanda en particular.
</p>
<p>
El meu interès pel llibre, tanmateix, no havia minvat en absolut. Per tant
vaig decidir tornar-lo a demanar. Aquest cop, per tal de garantir el tret,
vaig encarregar-lo amb l&#8217;enviament <q>pijo</q>. O sigui, a través d&#8217;una
empresa de transport (UPS, DHL o TNT, alguna d&#8217;aquestes que opera
internacionalment).
</p>
<p>
Lamento informar-vos que, aquesta vegada, tampoc va arribar. De fet, vaig
trucar a l&#8217;empresa de transport i em van dir que el llibre ja estava de
tornada als EUA (!). Un cop els va ser retornat el llibre, Amazon em va
reemborsar les despeses. O sigui, que per aquesta segona comanda no vaig
perdre diners.
</p>
<p>
<img src="/weblog/resources/aranzel.jpg" style="margin: 4px; float: right;" alt="Imatge d'una balança amb bitllets" title="Impostos">Recuperant la qüestió dels aranzels. Quan hom escull utilitzar una empresa de
transport, aquesta declara absolutament tot a l&#8217;aduana. De forma que jo ja
sabia que el que farien és posar-se en contacte amb mi per tal de pagar els
aranzels que <a
href="http://pdl.iec.es/entrada/fitxa_DIEC.asp?MOCODI=40662&#038;Page=diec">meritava</a>
el maleït llibre. Però no ho van fer, i això em va fer sospitar.
</p>
<p>
Amazon està dissenyada com un supermercat. Està tot suficientment ordenat com
per trobar les coses, o com a mínim poder-t&#8217;hi aproximar, 
però suficientment desendreçat com per fer-te perdre
temps donant voltes. També cal dir que jo no he estat mai massa hàbil amb
Amazon. Les meves sospites es van dirigir a l&#8217;adreça d&#8217;enviament de les
comandes <b>estava malament!!!</b>
</p>
<p>
Bé, malament malament no. Només que al numéro de telèfon li faltava una xifra.
La resta estava bé. Això va ser suficient com per impedir que el transportista
es posés en contacte amb mi, però no hauria d&#8217;haver afectat en absolut la
primera comanda, vaja, crec que no els hauria de preocupar que el número de
telèfon estigués bé o malament en un vulgar enviament postal.
</p>
<p>
I llavors sí que em vaig oblidar definitivament de tot l&#8217;assumpte. Aquí cal
remarcar que a partir d&#8217;ençà prioritzo les compres a la Unió Europea, tarden
una mica menys i no hi ha aranzels, o sigui que compro a Amazon UK i Amazon
França. El problema és que els millors preus, donat el canvi Euro/Dòlar i fins
i tot si hom hi inclou les despeses d&#8217;enviament, els llibres a Amazon USA
a vegades surten més barats.
</p>
<p>
Com deia em vaig oblidar de l&#8217;assumpte d&#8217;aquest llibre en qüestió. El llibre
maleït.
</p>
<p class="centrat">
&diams;&nbsp;&diams;&nbsp;&diams;
</p>
<p>
Fa uns dies vaig rebre dos avisos postals, <q>1º aviso</q>, de paquet a
Correus. Un venia d&#8217;Alemanya i l&#8217;altre d&#8217;Estats Units. Per al d&#8217;Alemanya
podria, a molt estirar, coincidir amb una comanda que no m&#8217;ha arribat encara
(<tt>¬_¬&#8221;</tt>) de <a href="http://www.cdjshop.com/">CDJShop.com</a> (hauré de revisar
l&#8217;adreça? xD). Però aquesta empresa és britànica, crec, i no té molt de sentit
que vingués d&#8217;Alemanya. Clar que a correus treballen d&#8217;una forma peculiar,
un cop tenia un paquet de <q>Jamaica</q> i després va
resultar ser que venia del barri de <a
href="http://en.wikipedia.org/wiki/Jamaica,_Queens">Jamaica</a> al districte
de <a href="http://en.wikipedia.org/wiki/Queens">Queens</a> de <a
href="http://en.wikipedia.org/wiki/New_York_City">Nova York</a>&hellip;
Pel segon avís, no tenia ni la més remota idea de què podria ser.
</p>
<p>
<img src="/weblog/resources/logo_correus.jpg" style="float: right; margin: 4px;" alt="Logo de Correos de España" title="Logo de Correus">Quan vaig anar a correus a buscar els dos paquets, ja la treballadora
em va fer una mala cara com dient <q>ahà!</q>. Quan va tornar venia amb dos
saques blaves, que si no ho vaig entendre malament, se suposa que ells no
poden obrir, que l&#8217;havia d&#8217;obrir jo. I la dona em va dir que feia molt de
temps que ho tenien allí. Va mirar l&#8217;etiqueta del paquet i segons aquesta
el estava allí des del juliol del 2006 (???). Cada saca contenia un paquet
d&#8217;Amazon <tt>:D</tt> Quan els vaig obrir a casa eren dos exemplars del llibre
que vaig encarregar feia 2 anys abans i dels quals només havia pagat un, el
segon era el reenviat per Amazon quan vaig queixar-me.
</p>
<p>
Segurament a correus es van oblidar o van perdre la informació del paquet. La
qüestió és que jo no vaig rebre mai els avisos originals, tot i que la
treballadora va dir-me que sí (què ha de dir, és clar). En fi, segurament mai
no treuré l&#8217;aigua clara de què va passar amb aquesta comanda allà al 2005.
</p>
<p>
L&#8217;única cosa dolenta de la història és que quan jo vaig fer la comanda el 2005
el llibre anava per la tercera edició i ara fa poc ha sortit la <a href="http://www.amazon.com/Computer-Architecture-Fourth-Quantitative-Approach/dp/0123704901/ref=pd_bbs_sr_1/102-8551424-0875352">quarta </a><tt>^_^U</tt></p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roger-ferrer.org/archives/126/feed</wfw:commentRss>
		</item>
		<item>
		<title>L&#8217;Anna, el Xavi i els infinits.</title>
		<link>http://blog.roger-ferrer.org/archives/125</link>
		<comments>http://blog.roger-ferrer.org/archives/125#comments</comments>
		<pubDate>Mon, 13 Nov 2006 22:40:04 +0000</pubDate>
		<dc:creator>rofi</dc:creator>
		
		<category><![CDATA[Parides]]></category>

		<guid isPermaLink="false">http://rofi.pinchito.com/weblog/archives/125</guid>
		<description><![CDATA[Anna, el que et vol explicar el Xavi és una mica místic. Segurament tampoc ajudaré a que en treguis l&#8217;aigua clara però ho intentarem.


Imagina que tens un sac infinit de boletes de colors i que totes, absolutament totes, les boles són diferents entre elles. En tens infinites, d&#8217;acord ? Sempre en pots treure una més. [...]]]></description>
			<content:encoded><![CDATA[<p>Anna, <a href="http://denea.bloc.cat/post/1316/113438">el que et vol explicar el Xavi</a> és una mica místic. Segurament tampoc ajudaré a que en treguis l&#8217;aigua clara però ho intentarem.
<span id="more-125"></span></p>
<p>
Imagina que tens un sac infinit de boletes de colors i que totes, absolutament totes, les boles són diferents entre elles. En tens infinites, d&#8217;acord ? Sempre en pots treure una més. Per moltes que en tinguis, a cada boleta de colors podries pintar-li un número a mesura que les vas treient. La primera boleta que treus tindria l&#8217;1, la segona el 2, la segona el 3,&#8230; Òbviament no acabaries mai, però cada boleta podria tenir un número, oi que sí? El que estàs fent és comptar les boletes, no hi ha cap problema que el teu sac sigui infinit.
</p>
<p class="centrat">
<img src="/weblog/resources/sac_boles_infinites.png">
</p>
<p>
Ara imagina que en realitat el teu sac de boletes és finit. Posem que en tens 3, la vermella, la blava i la verda d&#8217;acord ? Ara suposem que fas grupets de boletes. Primer comences fent grupets de 1, per tant tens la vermella en un grupet ella sola, la blava en un grupet ella sola i la verda en un grupet ella sola. Et surten 3 maneres d&#8217;agrupar les boles d&#8217;una en una.
</p>
<p>
Continues i fas grupets de 2, per tant tens la vermella i la blava, la blava i la verda i la vermella amb la verda. Tens 3 maneres d&#8217;agrupar les boletes de dos en dos. Finalment si fas un grup de 3 boletes, com que en tens només tres, només pots fer un únic grup de tres boletes: el que les té totes. Mirem quants grups en surten de cada: 3 grupets de 1 bola, 3 grupets de 2 boles i 1 grupet de 1 bola. Això són 7 grupets. 
</p>
<p class="centrat">
<img src="/weblog/resources/conjunt_parts_finit.png">
</p>
<p>
Si ara afegíssim una boleta rosa al teu sac i miressis de nou quants grupets hi ha et sortirien 15, a saber: 4 grupets de 1 bola, 6 grupets de 2 boles, 4 grupets de 3 boles i 1 grupet de 4 boles. Creu-me, i sinó, fes tots els grupets.
</p>
<p>
Ara ve la part complicada, imagina&#8217;t que vas a fer això dels grupets amb el teu sac infinit de boletes. 
</p>
<p>
«Qui voldria fer això?!? Però si tinc infinites boletes!!! Això no es pot comptar!!!», deus pensar.
</p>
<p>
Al principi ja t&#8217;he ensenyat que les hem estat comptant, cada boleta individualment li hem pintat un número i això no suposava cap problema encara que el teu sac de boletes fos infinit. 
</p>
<p>
Ara el que farem es provar de comptar les boletes grupet a grupet, d&#8217;acord ? Viam, comencem, agafarem les boletes d&#8217;una en una i cada una la posarem en una bossa i llavors pintarem el número a la bossa, d&#8217;acord? Després treurem les boletes de les bosses i llavors farem grupets de dos i posarem els grupets de dos boletes a una bosses diferents (bosses noves que no hem pintat) i pintarem la bossa, li pintarem un número. I així bossetes una rere l&#8217;altra, primer les bossetes amb una bola, després les bossetes de dos boles, després les bossetes de tres boles, etc. Fixa&#8217;t que cada bosseta té un número finit de boletes a dins i que cada bosseta té un conjunt de boletes diferent a totes les altres. Òbviament aquí tampoc acabaries mai perquè tens infinits grupets de 1, de 2, de 3, &#8230; però almenys aparentment sembla que podríem comptar totes les bossetes. Insisteixo aquí comptar vol dir pintar un número a les coses que comptes.
</p>
<p>
Suposo que ja estàs pensant, «però no acabaré mai de comptar les bosses amb una bola per començar a comptar les de dues boles!!! No les comptaria pas totes!!!». D&#8217;acord, provem de posar números a les bosses d&#8217;una forma diferent. Mira, se m&#8217;acut que podem fixar una boleta a cada pas. Escollim una boleta i la posem en una bossa. Pintem la bossa. Treiem la bola, la posem en una altra bossa i n&#8217;agafem un altra. Pintem aquesta segona bossa. Treiem les dos boles, les posem en una bossa nova i pintem un número a aquesta bossa de tres boles. Mmm, no, tampoc, perquè no les comptaré pas totes així tampoc.
</p>
<p>
No cal que pensem més estratègies, no n&#8217;hi ha cap que et permetria comptar totes les bossetes. Quan teníem un simple sac de boletes el mecanisme d&#8217;agafar cada bola i pintar-li un número ens permetria comptar-les totes. Però ara no podem fer el mateix quan volem comptar els grups de boles (les bossetes), sempre ens en deixarem sense comptar. 
</p>
<p>
Perquè? Imagina per un moment que <b>sí</b> que poguessis comptar totes les formes d&#8217;agrupar les boles, o sigui, ets capaç de pintar-me cada bosseta amb un número, les pots comptar totes. El que tindries seria un conjunt de bossetes amb un número pintat a les quals els havies posat un cert número de boles, en algunes els vas posar només una bola, en d&#8217;altres dues, en d&#8217;altres tres, etc. Anem a fer una bosseta nova (li direm la bossa maligna) que no tingui cap bola de la bosseta que li vas pintar el número 1 (no sé quantes boles vas posar en aquesta bossa, no és rellevant), però que tampoc tingui cap bola en la bosseta que li vas pintar el número 2 (de nou tampoc sé quantes boles hi vas posar), ni tampoc del número 3 (ni idea de quantes voles vas posar tampoc), i així successivament, que no tingui boles de la bosseta 4, tampoc de la bosseta 5, etc.
</p>
<p class="centrat">
<img src="/weblog/resources/conjunt_parts_infinit.png">
</p>
<p>
No pateixis, tens infinites boles, la bossa maligna sempre la pots fer perquè cada bosseta la vas fer amb un número finit de boles i sempre en trobaràs una que no hi és. Bé, doncs em plau comunicar-te que la bossa maligna no l&#8217;has comptada perquè si ho haguessis fet voldria dir que alguna bossa té exactament aquestes boles però en omplir de boles la bossa maligna només hem agafat boles que no es trobaven en cap altra bossa i si l&#8217;haguessis comptada tindríem ja una segona bossa maligna, però en construir la bossa maligna no agafaríem les boles d&#8217;aquesta segona bossa maligna!!! Què absurd tot plegat!!! L&#8217;absurditat apareix d&#8217;assumir que podies comptar les bossetes on agrupaves boles! (o sigui, pintar un número a totes les bossetes)
</p>
<p>
Sense entrar en massa precisions matemàtiques que no venen al cas, el teu sac de boles infinites clarament té infinites boles (diguem-li &#8220;infinit-A&#8221;). Tot i tenir &#8216;infinit-A&#8217; boles cada bola la podies etiquetar amb un número, totes les boles acabarien tenint un número. Però a les bossetes (que també en tindràs infinites, anomenem-lo &#8216;infinit-B&#8217;) sempre t&#8217;acabes deixant bossetes sense etiquetar. I això és perquè d&#8217;alguna manera infinit-B és molt més gran que infinit-A. D&#8217;acord que ambdós són infinits, però el infinit del sac de boles es suficientment &#8216;petit&#8217; com perquè les puguis comptar, en canvi l&#8217;infinit de les bossetes és massa gran, no el pots comptar, no pots pintar un número a totes les bossetes mentre que sí que podies fer-ho a totes les boletes.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.roger-ferrer.org/archives/125/feed</wfw:commentRss>
		</item>
	</channel>
</rss>
