La pila, el montículo y las variables de referencia (The stack, the heap and the reference variables)

A pesar de tener años programando este era uno de los temas que no lograba comprender al cien por ciento, después de investigar un poco entendí que lo desconocía incluso más de lo que pensaba, ya que aunque realmente sea un tema muy "simple" y pareciera al principio no muy crítico (debido quizás al Garbage Collector), resulta necesario conocerlo para comprender como se comporta nuestro programa en memoria, y para conocer cómo resolver conscientemente esos frustrantes errores de "StackOverFlowException" y "HeapOverFlowException" (java.lang.OutOfMemoryError en este caso), cabe mencionar que los temas abarcados aquí están enfocados a Java, aunque también pueden aplicar a otros lenguajes.

La pila y el montículo (The Stack and the Heap)

Primero que nada debemos conocer que existen dos espacios en donde se ejecutan nuestras aplicaciones, uno de ellos es la pila (Stack), en ella se guardan las variables locales y los métodos en ejecución, el otro es el montículo (Heap), en el se guardan las variables de instancia y los objetos. Cada Hilo (Thread) de la aplicación tiene su propia pila (Stack) pero todos comparten el mismo montículo (Heap), las variables y métodos de la pila (Stack) son eliminados al terminar su ejecución, las variables y objetos del montículo (Heap) son eliminados al no tener ninguna referencia hacia ellos y a capricho del Garbage Collector (al menos en Java y C#, aquí los gurús de C aplican el clásico "Ha Ha" con voz del Nelson), primero nos enfocaremos en la pila (Stack).

La pila (Stack)

Quizás una de las preguntas existenciales más difíciles es ¿De cuánto espacio dispone la pila (Stack)?, y la respuesta es un rotundo depende, incluso entre las mismas versiones de JVM (Java Virtual Machine) en distintas maquinas depende, y su explicación y configuración da para otra publicación más (insertar link cuando se tenga) por lo cual no trataremos aquí a fondo ese tema y solo te diremos que depende de la JVM, el sistema operativo, la configuración y el hardware, la siguiente pregunta a resolver sería ¿Cómo funciona la pila?, lo cual explicaremos a grandes rasgos, pero primero necesitamos un pequeño código para la explicación.

public class Program
{
                static int sumNNumbers(int n)
                {
                               if (n == 1)
                               {
                                               return 1;
                               }
                               else
                               {
                                               return n + sumNNumbers(n - 1);
                               }
                }
               
                public static void main(String[] args)
                {
                               System.out.println("Sum of the first 5 numbers: " + sumNNumbers(5));
                }
}

La pila (Stack) funciona como su homónima estructura de datos pila, el último elemento en llegar es el primero en salir (Last In First Out, LIFO), su comportamiento es parecido a una pila de objetos, por ejemplo una pila de platos si queremos añadir un nuevo plato a la pila lo ponemos en la cima, cuando queremos retirar un plato tomamos también el de encima.

Lo mismo sucede en la pila (Stack), y en cada llamada se almacena lo siguiente:

·         La dirección a la que se debe retornar después de la llamada.
·         Los datos pasados como parámetros de la llamada.
·         Las variables locales utilizadas por la función llamada.
·         Los datos devueltos, si la función los devuelve.

Si ejecutamos el código arriba expuesto, a grandes rasgos la pila se comportaría de esta manera:

·         El método main es puesto en la pila (Stack), con la variable args como parámetro.
·         El método println es puesto en la pila (Stack), con la dirección a la cual debe retornar después de su llamada y con su parámetro que es un String.
·         El método sumNNumbers es puesto en la pila (Stack), con la dirección a la cual debe retornar y con un entero como parámetro.
·         El método sumNNumbers es llamado recursivamente, puesto en la pila (Stack) n veces, con todos sus datos (dirección retorno, parámetros).
·         Una vez que llega a su último llamado, este es puesto en la pila (Stack), con la dirección a la cual debe retornar, un entero como parámetro, y al terminar su ejecución su valor de retorno, después regresa a su línea de retorno, devuelve el resultado y finalmente elimina sus variables y parámetros de la pila (Stack).
·         Se insertan uno por uno los valores de retorno del método sumNNumbers, y también se eliminan uno por uno sus datos de la pila (Stack) según se entreguen resultados.
·         Se retorna a la función println imprime el resultado en pantalla, una vez terminada su ejecución elimina sus datos de la pila (Stack) y regresa el método main.
·         El método main termina su ejecución y elimina sus datos del Stack.

Internamente su comportamiento es más complejo pero para fines didácticos nos basta, la tercera pregunta sería ¿Por qué se genera un StackOverFlowException? Esto es debido a que el espacio de la pila (Stack) es limitado, y cuando algún método quiere insertar sus datos en la pila (Stack)  y no se tiene espacio suficiente se genera esta excepción. Un ejemplo sería un método que se llama recursivamente de manera infinita ó en C# una propiedad que se auto asigne.

El montículo (Heap)

Otra pregunta difícil es ¿De cuánto espacio dispone el montículo (Heap)? Al igual que la pila (Stack) depende de la JVM, el sistema operativo, la configuración y el hardware, y ¿Cómo funciona el montículo (Heap)? Es un espacio donde se guardan variables de instancia y objetos (recuerda que es Java), que en lenguajes como Java y C# no pueden ser eliminados directamente sino con el Garbage Collector, y en lenguajes como C deben ser eliminados explícitamente (free), en este caso nos enfocaremos en Java y un poco en el Garbage Collector.

Después de este mini examen (espero haber aprobado) vamos directo al tema que es responder completamente la última pregunta. Los datos guardados en el montículo (Heap) son las variables de instancia y los objetos, pero ¿Qué es una variable de instancia? Son simplemente las propiedades expuestas de los objetos (instancias), para ejemplificarlo crearemos una clase llamada Car

class Stereo
{
                public void turnOn()
                {
                               System.out.println("Really cool music!!!");
                }
}

public class Car
{
                String carModel; // Instance Variable
                int carYear; // Instance Variable
                Stereo carStereo; // Instance Variable
               
                public static void main(String[] args)
                {
                               Car car;
                               car = new Car();
                               car.carModel = "Sentra";
                               car.carYear = 2005;
                               car.carStereo = new Stereo();
                               car.turnOnStereo();
                }
               
                void turnOnStereo()
                {
                               this.carStereo.turnOn();
                }
}

En este ejemplo las variables de instancia son carModel, carYear y carStereo, quizás en estos momentos piensas ¡¡Oye carStereo es un objeto también!! Pero carStereo no es un objeto sino una variable de referencia, ¿Qué es una variable de referencia?... Se explicara más adelante.

Volviendo al montículo (Heap), los objetos también son guardados en el mismo, en el código de Car hemos creado dos objetos, un objeto Car y un objeto Stereo y la instrucción que reservo la memoria, creo los objetos y regreso las referencias de los objetos es new, y ¿Cómo eliminamos los objetos? Eliminando todas las referencias hacia ese objeto, es decir eliminando las variables de referencia ó apuntando estas a otros objetos, aunque esto no los elimina los hace elegibles por el Garbage Collector quien finalmente es el encargado de eliminarlos.

Por último ¿Por qué se genera un java.lang. OutOfMemoryError? Al igual que la pila (Stack) el montículo (Heap) también es limitado, el JVM se asegura a través del Garbage Collector de tener la mayor cantidad de memoria disponible, cuando el Garbage Collector no puede recuperar suficiente memoria para la creación de un nuevo objeto se generá este error.

Variables de Referencia (Reference Variables)

Las variables de referencia, son tipos de datos especiales que guardan la referencia al objeto, el tipo de objeto y datos acerca de como acceder a los atributos y métodos del mismo, aunque es muy común en Java decir que los objetos se pasan por referencia en realidad no es exactamente así, lo que realmente sucede es que se hace una copia de una variable de referencia a otra, es decir se copian los bits de una variable a otra y como ambas hacen referencia al mismo objeto pareciera que se ha pasado el objeto por referencia, el código de abajo ejemplifica esta situación.

public class Cat
{
                String catName;
               
                public static void main(String[] args)
                {
                               Cat cat = new Cat();
                               cat.Name = "Meow";
                               System.out.println(cat.Name); // Imprime Meow
                               setCatName(cat);
                               System.out.println(cat.Name); // Imprime Meow
                }
               
                static void setCatName(Cat cat)
                {
                               cat = new Cat();
                               cat.Name = "Presley";
                               System.out.println(cat.Name); // Imprime Presley
                }
}

En el método main se crea un objeto Cat que es referenciado a través de la variable de referencia cat, y se le asigna el nombre "Meow" y se imprime, después se pasa como parámetro esta variable de referencia para el método estático setCatName, dentro de este se crea un nuevo objeto y se asigna a la variable de referencia que había sido pasada como parámetro, se le da el nombre "Presley" y se imprime, al regresar al método principal y volver a imprimir se muestra la cadena Meow, ¿Por qué no se imprimió Presley?, esto es debido a que al utilizar la instrucción new se creó un nuevo objeto y se referencio en la variable de referencia pasada como parámetro, a partir de ese momento las dos variables dejaron de referenciar al mismo objeto por lo que los cambios realizados en SetCatName no afectaron a la objeto original cat.

Grabar escritorio del pc desde la consola con ffmpeg

Como su nombre lo dice el día de hoy les mostraré como grabar la pantalla con la consola con un script usando la biblioteca ffmpeg, es muy sencillo solo tenemos que ejecutar en la consola. Para openSUSE.

zypper install ffmpeg

Después de instalarse tenemos lo que necesitamos para poder grabar nuestra pantalla desde la consola. ;)

Tenemos que ejecutar el siguiente comando:

ffmpeg -f alsa -ac 2 -i hw:0,0 -f x11grab -s $(xwininfo -root | grep 'geometry' | awk '{print $2;}') -r 10 -i :0.0 -sameq -f mp4 -y output.mp4

Bueno cuando terminen sólo detienen el script y listo, acá les dejo un videotutorial que hice



Saludos y espero que les sirva!

Reiniciar Campo Identity en SQL Server


Bueno espero les sirva este post, ya que yo cada vez que necesito hacerlo lo tengo que buscar para saber como se hace.
Los valores identity aumentan de forma secuencial, si eliminamos los registros de una tabla, el valor Identity no se inicializa, sino que continua con su último valor.
Para poder reiniciar el campo se ejecuta la siguiente instrucción:
1DBCC CHECKIDENT (<nombre_tabla>, RESEED,<valor_inicial>)
Eso es todo, Saludos.

Agregar programas al inicio de sesión en GNOME3

Buenas SQLeros, el día de hoy comparto con ustedes un tip que me gusto mucho y me fue de gran ayuda a la hora de usar Dropbox en openSUSE 12.2, dado que el proceso lo tienes que ejecutar cada vez que necesitas que se sincronicen las carpetas en tu PC. 

Instalar Monodevelop 3.0.5 en OpenSUSE 12.2


Buenas noches SQLeros el día de hoy vamos a instalar MonoDevelop desde el código fuente porque para esta fecha no se encuentra un paquete precompilado para OpenSUSE 12.2, aparte de eso la versión que esta para los repositorios de OpenSUSE es la 2.8.x y esa tiene un bug cuando seleccionas una solución te manda una excepción.


Nos dirigimos a la dirección http://monodevelop.com/download y seleccionamos la opción Source Code. Para este caso la url es la siguiente lo descargamos con: 

  • wget http://download.mono-project.com/sources/monodevelop/monodevelop-3.0.5.tar.bz2

Después lo descomprimimos para poderlo instalar, usando: 

  • tar -xvf monodevelop-3.0.5.tar.bz2

Ingresamos en el directorio monodevelop3.0.5 con: 
  • cd monodevelop3.0.5

Ahora vamos a configurar el paquete, usando: 
  • ./configure --prefix=`pkg-config --variable=prefix mono`
Ahora terminando la ejecución del comando usamos: 
  • make
  • make install
Esperamos y ¡listo!

Acá les dejo una captura de pantall del MonitoDevelop

Cuando el mejor cifrado tiene setenta años de antigüedad: el caso de la paloma mensajera 40TW194


Este articulo me gusto mucho y se los comparto. :D
paloma mensajera mensaje cifrado 40TW194
Hay veces en las que la era de la información en la que vivimos hace que obviemos algunos sucesos, calificándolos de demasiado antiguos. Incluso de primitivos. Pero hay ocasiones esos casos obsoletos y aparentemente simples dejan boquiabiertos a los mejores ingenieros de nuestros días. Es el caso de la paloma mensajera 40TW194, con un mensaje de la segunda guerra mundial que hasta ahora nadie ha sido capaz de descifrar.

Cambiar el HostName en OpenSUSE


Un nombre de equipo o hostname, es un nombre único y relativamente informal que se le da a un dispositivo conectado a una red informática. El nombre de equipo suele ser una palabra sencilla elegido por el administrador.
Luego de instalar openSUSE puedes encontrar que el nombre de equipo asignado por el instalador no es el más adecuado o conveniente. Pero cambiar el nombre de equipo es algo simple, tanto si lo realizamos desde la consola o utilizando YaST, y bautizar tu equipo con un nombre más a tu gusto.

Parametros Tipo Tabla en SqlServer 2008 (parameters type table in SqlServer 2008)


Los parámetros con valores de tabla ,son una nueva característica introducida en SQL Server 2008.

En versiones anteriores de SQL Server, no es posible pasar una variable de tabla en el procedimiento almacenado como un parámetro, pero ahora en SQL Server 2008 se puede utilizar con valores de tabla de parámetros para enviar varias filas de datos a un procedimiento almacenado o una función sin crear una tabla temporal o pasar tantos parámetros.

Hola a todos,
Ahora les traigo una forma de deshabilitar la combinación de teclas alt+F4 en una ventana en WPF con C#.
Para empezar debemos agregar el evento de KeyDown y Closing a nuestra ventana la cual quedara así:
1<Window x:Class="WpfApplication1.Window1"
4        Title="Window1" Height="300" Width="300" WindowStyle="None"WindowStartupLocation="CenterScreen"
5        Closing="Window_Closing" WindowState="Normal"
6        KeyDown="Window_KeyDown">
7    <Grid>
8    </Grid>
9</Window>
la cual tendra un codigo .cs así:
01public partial class Window1 : Window
02    {       
03        public Window1()
04        {
05            InitializeComponent();
06        }
07        private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
08        {
09          
10        }
11        private void Window_KeyDown(object sender, KeyEventArgs e)
12        {
13          
14        }
15        private void button1_Click(object sender, RoutedEventArgs e)
16        {
17          
18        }
19    }
Una vez teniendo esto agregamos una variable de tipo bool que nos servirá como bandera para saber cuando fue presionada la combinación de teclas alt+F4
1private bool _altf4 = false;
Agregamos las siguientes lineas a nuestro evento KeyDown, con el cual sabremos cuando fueron presionadas las teclas alt+F4:
1private void Window_KeyDown(object sender, KeyEventArgs e)
2     {
3         if (e.SystemKey == Key.F4 &&(Keyboard.IsKeyDown(Key.LeftAlt)||Keyboard.IsKeyDown(Key.RightAlt)))
4         {
5             _altf4 = true;
6         }
7     }
luego agregamos el siguiente código al evento Closing
1private void Window_Closing(object sender, System.ComponentModel.CancelEventArgs e)
2        {
3            if (_altf4)
4                e.Cancel = true;
5            _altf4 = false;
6        }
y seria todo al ejecutar nuestra aplicación la combinación de teclas alt+F4 quedara deshabilitada de nuestra ventana.
Bueno por el momento es todo, espero les sirva de algo y si les servio no olviden comentar.
Salu2.