Ver Mensaje Individual
  #1  
Antiguo 28-01-2009
poyo poyo is offline
Miembro
 
Registrado: ene 2009
Posts: 47
Reputación: 0
poyo Va por buen camino
Reflexiones acerca de _CopyObject

Siempre me causó curiosidad el system.pas. Es como una caja de pandora llena de sorpresas.

Nuestro colega Al planteó dos incógnitas aquí (mensaje #7):
1) ¿basta una llamada a _CopyObject para copiar todo el objeto por completo?

2) ¿en qué situaciones emplea Delphi la función _CopyObject?.

Resulta que estuve urgando y urgando.. poniendo los manos (hasta los hombros inclusive) en el barro. Vamos a ver...

1) Supongo que esta que voy a responder ya se sabe: la función _CopyObject, al ser parte de la "magia del compilador" no puede ser llamada. Si quieres hacer algo semejante deberás:
a) copiar dicha función en otro Unit (y _Copyrecord y sus dependencias: _VarCopy, _CopyArray, _IntfCopy, y unas cuántas más) y llamar a esta.
b) ingeniartelas para obtener el puntero en memoria de dicha funcion (ASM o no sé si con GetProcAddress se puede, hay que ver si está exportado el símbolo) y llamarla manualmente. Para ello Deberás compilar el proyecto con el Package de la RTL en Runtime (si no me equivoco, ahí está el unit System) Ver el porqué en rutime más abajo.

Aquí hay que tener en cuenta que _CopyObject llama a _CopyRecord.
_CopyRecord recibe como parámetros lo siguiente:

{ -> EAX pointer to dest }
{ EDX pointer to source }
{ ECX pointer to typeInfo }

Hace añares que no ando seriamente con assembler... (desde los 16 bits! jejejeje qué épocas aquellas! ), así que paciencia que esto me hace doler la cabeza
Tal como se dijo, _CopyRecord va iterando por los miembros del record y va haciendo un "Case" con información del Rtti, para sabér así a qué función para que esta haga la correspondiente asignación (copia).

2) En efecto, nuevamente citando a Al, _CopyRecord se llama cuando un registro es asignado (Registro1 := Registro2)
Sólo basta con poner un breakpoint en una línea como esa y seguirla con el debugger para ver que es así.

La respuesta a la pregunta nro. 2 seguramente generará nuevas incógnitas:

Según parece, No exite algún caso donde se utilice dicha función.

Nuevas incógnitas que les surgirán:
1) En qué me baso para decir esto?
2) De ser así, porqué se encuentra allí?

Respuestas a las nuevas preguntas:
1) me baso en lo siguiente:
a) Si uno compila un ejecutable con todo estático (sin la opción "Runtime Packages"), la función _CopyObject no es incluída en el archivo ejecutable por la simple razón que no se usa. Pueden buscar pero en mi caso fue en vano.
También, al hacer una asignación de registro a registro (Registro1 := Registro2), si ponen un breakpoint, van a ir a un puntero que hace n jump al código real de _CopyRecord. Si vajan, sin ejectura, con el scroll, van a ver que, más abajo, no se encuentra la función _CopyObject a continuación, donde debería estar.
b) Si al compilar se activa "Runtime Packages" y hace que las dll's de los paquetes (bpl's) rtl/vcl y demás vaya en runtime, allí sí tendrás el código, dentro de la dll correpondiente al rtl (rtlXXX.bpl, donde XXX es reemplazado por la versión de delphi). Si buscas dentro se puede encontrar. En mi versión, está al lado de CopyRecord.
Si reperimos el ejercicio anterior de poner un breakpoint en la asignacion del registro (para luego ir al código de la función _CopyRecord), se podrá ver que sí, realmente abajo (en mi versión), se encuentra el código de _CopyObject.
c) Siguiendo los pasos del punto anterio, una vez localizado desde el debugger el código de _CopyObject, le puse un Breakpoint al principio. Dicho breakpoint jamás fue ejecutado.
d) Pensé que podría llegar a ser producto de que, en mi caso, al ser una aplicación de prueba muy sencilla, no se ejecutara simplemente por carencia de su uso y supuse que, si utilizara de ratón de laboratorio a una aplicación más compleja dicha condición podría ser factible.
"Qué mejor que el mismo delphi!", pensé... y procedí a crear un package de diseño. Allí, en el initialization de un Unit puse un breakpoint en ASM ("int 3") justo una línea antes que una asignación Registro a Registro.
Luego compilé, al projecto le asigné como "Aplication Host" al mismísimo bds.exe (con su respectivo parámetro de personalidad "delphi") y procedí a la ejecución para poder debuggear. Allí, ejecutarse el "int 3", ubiqué _CopyObject, le puse un breakpoint (tal como antes lo había hecho) y reinicié el delphi (el que estaba debuggeando, claro).
Jamás se ejecutó dicho breakpoint.
Procedí abrir un proyecto, compilarlo, ejecutarlo, cerrarlo, abrir cantidades de wizards y bpl's de Desingtime y nada.
_CopyRecord se ejectura por todos lados pero de _CopyObject ni noticias.

2) Entonces, la GRAN incógnita: ¿Porqué está allí?
Sólo se me ocurren teorías ya que, al ser ajeno al equipo de desarrollo, otra cosa no puedo hacer.

teorías:
a) El código viene heredado desde viejas versiones. Tal vez de las primeras y, al ir cambiando los Líderes del proyecto, los desarrolladores, etc., ha quedado en el éter. Nadie sabe exáctamente porqué está ahí pero, por las dudas, la dejan ahí.
b) Es algo de uso muy interno, interno al compilador pero ajeno a las aplicaciones y al mismo RAD.
c) Es algo de uso muy muy interno, ajeno compilador y al RAD comercial, Tal vez haga uso de ella alguna herramienta internal de ellos o una versión especial (interna) de su compilador/rad.
d) es un cebo para diversión
d) Estoy completamente equivocado,además de desquiciado!

Ahora creo que es a ellos (los de Codegear) a quiénes deberíamos de preguntarles... si es que saben.

Yo me tiro por la primera, aunque no descarto las demás...

Al, Espero haber respondido espero haber respondido a tus dudas.

Cualquier otra duda y/o error, avisen.
Responder Con Cita