![]() |
Reto Delphi 2011
Hola a todos.
Ahora propongo este reto Delphi que me parece será más fácil de resolver que el anterior (esta vez no será necesario meternos con los registros de la CPU). ;) Tenemos una rutina de la cual sabemos que su última sentencia es una llamada a la función nativa GetMem:
Como es de esperarse P es una variable puntero y X un entero que indica el tamaño del bloque de memoria que GetMem deberá reservar y asignar a la variable P. T1 es una clase de la VCL de Delphi, cuyo código fuente podemos ver sin problemas. Proc1 es uno de los métodos públicos de T1. X es uno de sus campos privados (un miembro declarado en la sección Private de la clase), para el cual la clase no tiene propiedad o método alguno que nos permita conocer su valor. En nuestra aplicación tenemos una instancia de clase T1 (variable Obj), y desde algún lugar realizamos esta llamada:
Pero justo después de esa sentencia, necesitamos conocer el valor de X con el que Proc1 llamó a GetMem, es decir:
La pregunta es: ¿Qué podemos colocar en lugar de ese asterisco para que el mensaje mostrado por ShowMessage diga la verdad, y qué código habría que escribir para lograrlo? Desde luego, sin modificar los fuentes de la VCL. Recordemos que X es un campo privado de T1 y nuestro código de prueba (en mi caso hecho en Delphi 7), no forma parte de la misma unidad .pas que T1. Por lo tanto el compilador no admitirá un referencia explícita al campo Obj.X, ni siquiera derivando una clase de T1 (razón que me hace cuestionar de cuando en cuando la valía del nivel de visibilidad Private). No vale el uso de moldes de acceso tipo:
Estoy seguro que más de uno lo resolverá muy pronto. Cuando lo hagan, mencionen alguna pista si lo desean, pero por favor esperen un poco antes de publicar la solución completa. De esta forma la incógnita se mantendrá vigente por un tiempo considerable. Un abrazo en privado. Al González. :) |
¿Heap?
// Saludos |
Cita:
Si me esperan unas dos semanas quizá me anime intentar superar el reto, pero para ese tiempo seguro que ya fue descubierto y publicada la solución. Al, me dejaste sin opciones... mientras leía me decía fácil, le aplico un molde y se acabó; ya me dije que por algo es un reto. Ummm... estoy pensando: ¿una sigla, 4 letras? :confused: :rolleyes: Saludos, |
Cita:
Es pregunta, y si la respuesta es afirmativa entonces es una pista :D // Saludos |
Cita:
Cita:
Cita:
¡Si no estamos en La Taberna! :p |
No estoy muy seguro, pero creo que en lenguaje C sería más fácil :D
|
Cita:
Entonces no estamos pensando en las mismas 4 letras seguramente. :o :confused: Ha seguir pensando, tengo dos semanas para pensar. Espero poder dormir esta vez. Saludos, |
Cita:
|
Una pregunta: ¿P es una variable local al método Proc1, es una variable global, o es una propiedad de la clase? Y si es una propiedad, ¿es pública o privada?
Es que he tenido una idea... |
Cita:
|
Cita:
// Saludos |
Cita:
Pero mejor esperemos a que Alberto nos aclare mejor, ya sea para aplicar esa idea o para descartarla..:D Saludos...:) |
Cita:
La pregunta que hiciste sólo tiene una respuesta: sí. La función GetMem sí tiene que ver con el montón, lo cual es algo conocido. :) Cita:
Cita:
No obstante, cuando esto quede resuelto, podríamos discutir qué tan viable sería aplicar la solución que tienen en mente si P fuera un elemento público. Claro, si es que ambos están pensando en lo mismo que yo. |
Cita:
// Saludos |
Hola Al.
Creo que esta es una forma, vos diras si estoy en lo cierto... Archivo Adjunto 1889 Te envío la contraseña por pm. Un saludo.:) |
Me parece ingenioso lo que has intentado, ecfisa. Quizá algo así es lo que tiene en mente Román, pero le veo dos pegas o inconvenientes, como decimos en México.
Una es que teóricamente serviría si T1.Proc1 no tuviera más sentencias que reservaran bloques de memoria. ¿Qué tal si crea en su interior nuevas instancias de objetos, o si llama a otras rutinas que también ejecutan el procedimiento GetMem? La operación matemática que haces no sería válida. El otro inconveniente es que las funciones que reservan memoria suelen hacer alineación. Por ejemplo, si X tiene un valor de 847777, el resultado con la solución que propones aparece en mi pantalla como 847780. Román, espero dejemos atrás el mal entendido y no desistas de participar. Un abrazo. :) Al. |
Hola.
Habra que seguir buscando por otro lado... :rolleyes: Un saludo.:) |
Muy interesante... muy interesante! Ni siquiera me atrevo a decir que haré intento alguno. No soy muy bueno en las partes de más bajo nivel de Delphi.
|
Pues vaya, me has chafado. A ver qué hago y ahora. :(
|
Esto no tiene mucha ciencia, creo que en cualquier momento alguien nos sorprenderá con la solución. Pero está bien, les daré una segunda pista sólo porque estamos a la mitad del camino. :)
|
Dale de una ves con la segunda pista...:D:D
|
¿Y bien? ¿Qué ha sido de esto?
Creo saber cómo resolverlo aunque me desconcierta lo del GetMem pues con mi "solución" bastaría cualquier función/método que no altere el valor de X. // Saludos |
Cita:
Cita:
Cita:
|
Ya suponía yo que en el aviso en sí de la segunda pista estaba la pista. Sólo que a mi no me dice nada ni la primera, ni la segunda, ni la tercera, por lo que supongo que son caminos distintos. La solución que vislumbro consiste sencillamente en acceder al campo privado X. Cosa que es posible si se conoce el código fuente de la clase, que me parece es una de las premisas. Aunque no es una solución elegante y no la usaría en un programa :)
Agrego: Pensándolo bien, quizá sí esté en el mismo camino pues algo de lo que mencionas sí lo uso. // Saludos |
Pues coincido con Roman al decir que "consiste sencillamente en acceder al campo privado X". Y aquí se me encendió la lucecita y pregunto:
¿Se ha compilado con información de depuración o sin ella? ¡Zasca! Seguro que no se lo esperaba, maestro González. :D |
Cita:
No hay información de depuración porque el programa ha sido compilado para producción, y un campo como X no genera RTTI. :) Mejor sigan la pista #1, si bien esto es prescindible para llegar a lo que esa sigla significa. ;) |
Ja, ja, Pero eso ya es demasiado. Es como si un profesor te impidiera usar una solución aún siendo válida :)
Para mi que Ñuño y yo ya lo resolvimos, lero, lero. :) // Saludos |
Yo por algo preguntaba sobre cierta sigla de 4 letras :rolleyes: :D
Y estoy re perdido. Esas pistas para mi ni Arthur Conan Doyle se las imagina para las aventuras que ha escrito; que me han resultado complicadas de sacarle algo :o Yo de este reto mejor paso, que tengo mi cabeza pensando en mis propios retos... y en los del mecánico que me ajusta los tornillos :( Saludos, |
Yo no sé ni a que sigla se refiere. Es más, ni siquiera sé cuál es la primera pista, y la tercera mejor ni releerla porque da dolor de cabeza :p
// Saludos |
Cita:
Más que reto, se me hace una adivinanza :D Y si a ti te da dolor de cabeza, entonces ¿a mi? :( :eek: Saludos, |
Cita:
Cita:
Cita:
Cita:
|
Cita:
// Saludos |
Cita:
Cita:
Voy a tener que llamar al área 51 porque parece que se fugaron de allí. ¿Cómo le hacen para saber tantas cosas? :D Evidentemente hay cosas que mi cabeza no logra entender y captar porque no tiene la preparación... pero esto... ¡se me hace que es más fácil encontrar la teoría unificadora de la física! :D :p Supongo que en una semana van a dar conocer la solución ¿no? ;) Porque me han dejado intrigado. Saludos, |
He de decir que lo de las siglas sigo sin entenderlo, aunque el término maleable tampoco me convence mucho.
Lo que es cierto es que la respuesta es mucho más sencilla de lo que parece, tal como lo comentó Al desde un principio. También es elegante y segura de usar, no como mi segunda solución, que voy a esbozar para que los demás no tomen el camino equivocado: Los campos en un objeto se acomodan de manera similar a un registro con un primer campo oculto que es la referencia a la clase a la que pertenece el objeto. Los campos aparecen en el orden en que están declarados y cada objeto guarda los campos de su clase y los de todas sus ancestras. Así pues, el método "sucio" de acceder al campo X pasa por saber el offset o desplazamiento del campo en el objeto y acceder libremente:
Calcular dicho offset no es tan sencillo pues hay que tomar en cuenta el alineamiento que menciona Al. Sin embargo, puede hacerse examinando el código fuente de la clase. Si la clase tiene ancestros nos podemos ayudar con AncestroDeClaseDeObj.InstanceSize, ya que InstanceSize sí toma en cuenta el alineamiento. Aún así, hay que examinar los campos de la clase final hasta llegar a X. // Saludos |
¡¡¡ ¿¿¿Ya lo han descubierto??? !!! :eek:
Yo es que no he entendido las pistas, que parecen encriptadas :confused: |
Ahora que leo lo comentado por Román veo que mi idea estaba bien encaminada, por eso dije:
Cita:
|
Pero ojo, la solución que esbocé no es la que busca Al.
// Saludos |
Cita:
// Saludos |
1 Archivos Adjunto(s)
Bueno, aunque sabía la solución, no me decidía por la forma de implementarla. Aquí pongo una opción.
Contestando a Cita:
y el código que hay que escribir está en el archivo adjunto. La contraseña, para quien quiera ver la solución, es el tipo de datos (todo en minúsculas) involucrado :) Por cierto, del primer intento (fallido) de solución, que tenía que ver con las funciones del Heap, sale este koan: Cita:
|
| La franja horaria es GMT +2. Ahora son las 14:02:50. |
Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2026, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi