lunes, junio 11, 2007

Referencia y valor

En programación creo que una de las primeras cosas que te enseñan es que las variables se pueden pasar a las funciones por referencia o por valor. Por explicarlo brevemente, por valor estás pasando el valor de la variable en una copia, de tal forma que la variable original permance inmutable; mientras que por referencia pasarías la misma copia de la variable, haciendo que la función pudiera modificarla. Cada una de estas maneras tiene sus ventajas e inconvenientes y para adentrarnos más en la explicación necesitaríamos empezar a explicar los punteros. Pero...
¿qué ocurre si modificas la dirección? (...) tendrás un bonito puntero apuntando a una zona de memoria liberada que en cuanto la toques generará un bonito error
Esto de arriba, si no me falla la teoría, se llama vulnerabilidad del copón para ejecutar código arbitrario ;)

Fran (antes conocido como Neok) ha puesto un post que a mí me ha parecido muy bueno sobre el uso de los punteros de punteros (¿referencias a referencias?): Memoria dinámica. Evitaréis hacer programas tan tontamente vulnerables (las vulnerabilidades tontas son las más jodidas, y si no, buscad qué es el buffer/stack overflow).

Etiquetas:

14 Comentarios:

Anonymous Fran ha dicho...

Pues gracias por lo que me toca. La verdad es que las vulnerabilidades de este tipo son a veces difíciles de encontrar porque muchas veces el código se ejecuta correctamente sin mostrar error, y otras veces sí que aparece el error.

Lo mejor es tener muchísimo cuidado al usar la memoria dinámica, y siempre controlar el espacio que reservas y comprobar que cuando copias/creas/reservas memoria es del tamaño indicado.

6:14 p. m.  
Anonymous Inagotable ha dicho...

La de bonitas violaciones de segmento que he tenido por los punteros ^_^ .

Son muy potentes pero también una fuente inesperada de posibles errores.

8:53 p. m.  
Blogger El Cerrajero ha dicho...

# Lek, se que tu si vas a saber apreciar esto xD

9:38 p. m.  
Blogger Lek ha dicho...

Vaya grillada se ha pegado el dibujante, ¿que no? Ya te he puesto que con la explicación sí que me he enterado ^^

9:18 a. m.  
Blogger El Cerrajero ha dicho...

xDDDD

Me gustaría saber si al tío le vino la inspiración de serie o tuvo que llamar a su primo, ese que camellea xD

1:01 p. m.  
Anonymous Troxer ha dicho...

Yo siempre he pensado que en la mayoría de casos en que hay que hacer virguerías y cosas "raras" con punteros y demás, el problema está en un mal diseño o una mala codificación.

Al fin de cuentas, en los lenguajes con máquina virtual no hay punteros y no por ello se dejan de hacer aplicaciones.

Cuantas menos indirecciones de indirecciones de las indirecciones al puntero del puntero, mejor.

2:39 p. m.  
Anonymous Fran ha dicho...

Troxer eso de que en los lenguajes de programación con máquina virtual (como Java) no hay punteros se podría discutir, ya que un objeto es básicamente un puntero a una estructura, otra cosa es como los gestione/trate el lenguaje.

En Java existe el recolector de basura, que va liberando memoria según le apetece, y que posiblemente sea uno de los mayores problemas de Java.

Yo prefiero la opción de hacer free (objeto), al igual que new objeto (), pues la memoria podría liberarla cuando yo sé que no me va a hacer falta.

Y lo de punteros a punteros en lenguajes con VM, como Java, seguro que tienes casos:

this.objeto.metodo-que-devuelve-objeto ().metodo ();

Otra cosa es que sea más fácil de leer que no lo dudo, y que conste que soy defensor de C y Java, dependiendo de para qué uno es más válido que otro.

7:43 p. m.  
Anonymous Troxer ha dicho...

Fran

Entonces quizás no tendría sentido llamarlo puntero sino más bien referencia, que es como creo yo que se deben llamar a estas cosas en Java y C#. Digamos que para mí los punteros de verdad son los de C y C++, por ejemplo, más que nada porque están en mis pesadillas universitarias.

Ya sé que el recolector de basura tiene muchos detractores, pero sinceramente que sea más lento que hacerlo tú no significa que sea peor. Creo que hay que abrazar los cambios que facilitan el desarrollo, y está claro que un sistema que te gestiona la memoria. ¿Qué es más lento que hacerlo a mano? Bueno, pues le echas más hierro al asunto y a tomar por ... ¡Que las compañías que fabrican hardware también tienen derecho a prosperar! ;)

No sé, supongo que yo soy la opinión de alguien que programa pero que no gusta mucho de las virguerías "frikis".

Sobre la validez de C y Java, está claro que C es siempre más válido que Java porque Java es una puta mierda (no te ofendas lek ;) .

10:24 a. m.  
Anonymous Fran ha dicho...

Troxer aceptamos barco, llamesmole referencias.

Facilitar el desarrollo, eso es en lo único que se escuda la gente al defender a Java, y es cierto, en Java se tienen un montón de cosas que facilitan el desarrollo, pero ¡ojo! en C también existen librerías para facilitar el desarrollo, tienes Glib (la librería de GNOME) que te proporciona hash, listas, strings, ... ¡Todo como en Java! Claro que en Java ya la lleva incorporada en el núcleo, y no tienes que distribuir tu programa junto a la librería, aunque tienes que distribuir tu programa junto al JRE de turno, con lo que no sé qué es peor.

Yo soy de la opinión que Java está muy bien, programar en él es sencillo y ofrece muchas cosas chulas, polimorfismo, sobrecarga, interfaces, una POO decente, ... Pero hay que ver, que en Java deberían proponer cambios en algunas cosas, o por lo menos dar alternativas, como es en el caso del recolector, yo creo que nadie se moriría por tener que hacer un release/free de los objetos que no va a usar más.

1:39 p. m.  
Blogger Lek ha dicho...

Fran, al menos a mí sobre lo del recolector de basura me enseñaron que cuando no quisiera un objeto lo mejor era marcarlo para "destrucción" (poniendo a null, por ejemplo, vaciándolo en el caso de listas...). Algunas de esas técnicas han quedado desfasadas porque el propio recolector de Java ha mejorado, pero otras siguen siendo válidas ;)

Con respecto a los cambios, se está en ellos. Por ejemplo, el JRE modular, la eliminación de características desfasadísimas del lenguaje... y siendo como es desde hace poco OpenSource es de esperar que empiece a "cambiar" mucho más rápido ahora.

Troxer, no me ofendo, aunque me parece una generalización que se olvida de una ventaja muy importante sobre casi todos los demás lenguajes: es multiplataforma ~100%. Chonadas tienen todos, la cuestión es que te gusten más o menos :)

3:44 p. m.  
Anonymous Troxer ha dicho...

@Lek:

Lo de que es 100% multiplataforma lo has dicho de broma ¿no? Venga, por favor, no sigamos diciendo eso a estas alturas, que hay mucha gente ahí fuera que ha sufrido migrar una aplicación de un entorno a otro en Java.

En Java una aplicación es 75% multiplataforma, como mucho. El resto es tener que andar cambiando cosas, tocar historias y demás para que cuadre y se vea o funcione igual en Windows que en Linux.

Además, que yo no sé cuanta gente está ahí fuera desarrollando aplicaciones para escritorio con Java, yo creo que más bien pocos comparados con los que hacen desarrollos web y J2EE y para hacer eso no necesitas un lenguaje multiplataforma.

@Fran
¿Para qué quieres un Java que no haga esas cosas "fáciles"? Usa C. Por mucho que aligeren Java, nunca será tan rápido como C por lo que si lo que de verdad quieres es tunear tu aplicación, a darle al C. Claro, que si todo el mundo pensara como tú, lo mismo seguíamos usando ensamblador... :P

9:48 a. m.  
Anonymous Fran ha dicho...

Troxer es que ensamblador es el rey de los lenguajes, vamos ¡no me jodas!

Yo lo único que he dicho es que el recolector de basura de Java es basura (valga la redundancia), y que o se va mejorando (supongo que en cada versión mejora) o deberían dar alternativas para liberar la memoria por tu cuenta, esto no quiere decir que lo tengas que hacer, sólo que si quieres lo hagas. Como dice Lek, hay trucos para hacer que el recolector se de cuenta antes de que ese espacio de memoria lo quieres liberar, marcando null o "vaciando" el objeto.

Y, por supuesto, si quiero una aplicación rápida usaré C. Pero sigo diciendo que Java me gusta y lo usaré cuando crea que me será útil.

11:48 a. m.  
Blogger Lek ha dicho...

Troxer, una aplicación Java bien hecha es casi 100% multiplataforma... y no necesariamente tiene que ser una aplicación de escritorio para que necesites que rule en un Win o un RedHat...

Yo me he encontrado teniendo que cambiar cosas, como tú dices, pero por culpa mía. Por poner un ejemplo, que en lugar de usar el "File.separator" lo pongo literal a cañón (y, claro, luego no rula). Pero, ¿bien hecho? Salvo cosas muy muy específicas de una u otra plataforma, te debería compilar exactamente igual.

3:45 p. m.  
Anonymous Fran ha dicho...

Lek incluso en los File vale ponerlo como en Linux, es decir "/ruta/a/donde/quieras" y funciona en Windows, lo que no sé es si toma el raíz como C: siempre o como la unidad donde ejecutes el programa. :S

(Supongo que a eso te referías)

5:02 p. m.  

Publicar un comentario

<< Principal