Acerca de:

Este blog contiene los códigos, ejemplos y bases de datos que he usado cuando aprendía acerca de algún tema específico. En lugar de borrarlos (una vez dominado ya el tema), he decidido publicarlos :)

viernes, 14 de mayo de 2010

Fixed o no Fixed

Tengo el siguiente código:

using System.Drawing;
namespace SomeNamespace {
unsafe class SomeClass{

      private void One() {
            Point[] esq = new Point[3];
            Point* p = &esq[0];
            Two(p);
            }
     private void Two(Point *p) {
            // Write your ad here :)
            }
      }
}

Y pareciera que no hubiera error, pues he declarado la clase como "insegura" y estoy pasando un puntero a un dato tipo "Point" como parámetro a otra función. Y aún así me sale este error:

"Error  1 Sólo se puede adquirir la dirección de una expresión de tipo unfixed de un inicializador de instrucción fixed"

C# no deja usar punteros no "fijos" (es decir, cuyo valor, o dirección a la que apuntan, se puedan modificar). Esto es debido al colector de basura, que está siempre monitoreando la memoria, desasignando espacios de memoria, borrando objetos o moviéndolos a otras ubicaciones. Un puntero "fixed" evita que su valor apuntado sea movido a otra ubicación en la memoria, y así poder asegurarse que su valor no será reemplazado por otro sin que nos demos cuenta.

El código "fixed" sería:

using System.Drawing;
namespace SomeNamespace {
unsafe class SomeClass{
      private void One()  {
            Point[] esq = new Point[3];
         
            fixed( Point* p = &esq[0])
                   {
                        Two(p);
                   }
             }
     private void Two(Point *p)  {
            // Write your ad here :)
            }
     }
}



Según la documentación de Microsoft, es posible evitar usar "fixed" si se separa espacio en la pila para nuestros punteros. Esto se hacce con "stackalloc". La memoria se libera cuando se sale del método donde se separó el espacio en la pila:

using System.Drawing;
namespace SomeNamespace {
unsafe class SomeClass{
      private void One() {
            Point[] esq = stackalloc Point[3];
            Two(&esq[0]);    // también es válido: Two(esq);
            }
     private void Two(Point *p) {
            // Write your ad here :) 
            }
      }
}

1 comentario:

Anónimo dijo...

excelente explicacion, me sirvio de mucho ya que pocos sitio sen la red ofrecen tan buenos tutoriales como este.
thnaks