FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
|
Herramientas | Buscar en Tema | Desplegado |
|
#1
|
||||
|
||||
En qué versión de Delphi se ha corregido cierto problema en Vcl.OleCtrls.pas
Hola a todos,
Tratando de solventar el problema descrito en este artículo, he hecho los cambios en la unidad Vcl.OleCtrls.pas, tal como se indica en el artículo enlazado. Parece ser que se trata de un error bastante antiguo y que, al menos en Delphi XE2, todavía existe. Ahora bien, mi pregunta es, ¿podéis revisar la unidad Vcl.OleCtrls.pas en vuestro Delphi y decirme si el error está corregido, así como la versión de Delphi de que se trate? Creo que se entiende lo que quiero decir, pero, puesto que no sea así, por favor, decídmelo y trato de explicarlo mejor. ¡Muchas gracias a todos! Última edición por dec fecha: 23-11-2015 a las 20:21:51. |
#3
|
||||
|
||||
Hola,
Gracias por responder JOSEPE. Es curioso, porque, el código de Delphi 10 no es el mismo que en Delphi XE2 (que se supone todavía es erróneo) pero también es distinto a la solución propuesta en el artículo enlazado: Cita:
Cita:
Gracias de nuevo a todos. |
#4
|
||||
|
||||
Hola,
Por cierto JOSEPE, ¿podrías poner aquí también la implementación de "GetIUnknownProp" en Delphi 10? Está al lado de la de "GetIDispatchProp" y ambos parecen estar implicados en el problema. ¡Gracias! |
#5
|
||||
|
||||
Hola David.
El artículo que enlazas contiene esto en la cabecera: Cita:
Ahora bien, revisando su propuesta y la solución que Embarcadero implementó, te diría que ambas son equivalentes en resultado. Sin embargo, no hace falta sabiduría para darnos cuenta de que la segunda opción consume más ciclos de CPU, mientras que la primera es parca pero más eficiente. En la solución de Embarcadero, la sentencia "Result := IDispatch(Temp.VDispatch)" obtiene una copia de la interfaz contenida en Temp.VDispatch e incrementa en uno su contador de referencias. Luego la sentencia "IDispatch(Temp.VDispatch) := nil" disminuye en 1 ese mismo contador, lo cual, dada la sentencia anterior, se vuelve necesario. En cambio, en la solución que Marc Durdin propone, "Pointer(Result) := Temp.VDispatch" obtiene una copia de la interfaz sin incrementar su contador de referencias, por lo tanto sin necesidad de hacer un decremento explícito. La solución del artículo es más elegante y eficiente. Según los enlaces del autor, al parecer lo tomó de aquí. Mientras que el programador que escribió la corrección en Delphi Seattle parece haberse limitado a añadir una línea de parche, sin atender el problema de fondo. (La única justificación, aunque ligera, que podríamos darle a añadir esa línea de más, es que estuviera previendo que Embarcadero revisara el manejo de la estructura de los variants por parte del compilador). La causa del problema reside en que la estructura interna de un valor Variant —el tipo TVarData— es, valga la redundancia, un registro con parte variante. El compilador de Delphi no admite que en la parte variante de un record aparezca declarado un campo cuyo tipo lo haga emplear un contador de referencias, como es el caso de las cadenas de caracteres, las interfaces y algunos otros. Así que, para salvar esa limitante —que es bastante razonable y justificada—, algunos campos del registro variante TVarData fueron declarados como punteros genéricos: El problema con estos es que, al quedar el registro fuera de ámbito (la variable local Temp queda fuera de ámbito cuando GetIDispatchProp llega a su end), nada se encarga de revisarlos para ver si contienen algo que haga falta ser liberado. Muy al contrario de si VDispatch fuera un campo normal declarado de tipo IDispatch en lugar de Pointer. Así que al extraer valores que usan contadores de referencias de variables, parámetros, propiedades o campos explícitamente declarados con un tipo "comodín", como el Pointer, es menester recordar que ahí hay algo que habrá de ser descontado tras la extracción (solución de Embarcadero), o bien, evitar que aumente el contador utilizando un molde de tipo sobre el receptor (solución del artículo). El truco con esta opción es que el contador se mantiene intacto, y transfiere la responsabilidad de reducirlo al receptor del valor. En el ejemplo que nos ocupa, GetProperty pone en Temp.VDispatch una interfaz a la cual le incrementa en uno su contador de referencias, y la responsabilidad de restar ese 1 queda en el llamador de GetIDispatchProp (puesto que a él le pertenece Result). El intermediario GetIDispatchProp ni se entera de que está contrabandeando una interfaz. Espero esta pequeña contribución dé algún valor al tema. Al González. P.D. David: Te confirmo que en Delphi XE7 Update 1 el código de los métodos mencionados aún presentaban esa falla: Código:
function TOleControl.GetIDispatchProp(Index: Integer): IDispatch; var Temp: TVarData; begin GetProperty(Index, Temp); Result := IDispatch(Temp.VDispatch); end; ... function TOleControl.GetIUnknownProp(Index: Integer): IUnknown; var Temp: TVarData; begin GetProperty(Index, Temp); Result := IUnknown(Temp.VUnknown); end; Última edición por Al González fecha: 24-11-2015 a las 01:16:20. |
#6
|
||||
|
||||
Hola a todos,
Qué buena respuesta Al, me alegro mucho de no haber leído que el problema se ha resuelto en Delphi 10, con tal de haber podido leer tu respuesta. Muchas gracias, de verdad, puesto que además uno dudaba de qué solución emplear (la del artículo o la de Delphi 10) y ahora parece claro cuál puede ser mejor. El caso es que debe haber mucha confusión en todo esto, seguramente, porque algunos que nos llamamos a nosotros mismos programadores, en realidad pecamos de no saber de la misa la media de muchísimas cosas, como queda claro en mi caso, sin ir más lejos, con este problema conque me he topado. No sé si me excusará algo el hecho de que, buscando por internet sobre los problemas de la "ocupación" de memoria del control "TWebBrowser", algún que otro bien considerado programador (del que jamás dudaría de su capacidad) no llegó tampoco a acertar con una solución. Pero seguro que no tuvo tiempo. El caso es que de lo que dices entiendo que este problema puede estar también en otro tipo de controles, no sólo en el "TWebBrowser", y, en verdad puede ser un problema bastante curioso, puesto que este control en concreto (a fuerza de crear y destruir unos cuantos de ellos) puede terminar provocando un grave error. Yo no había notado el problema hasta mi proyecto App Builder, puesto que este hace un uso intensivo (demasiado intensivo, en mi opinión, habría que tratar de reducirlo al máximo) del control "TWebBrowser". Un usuario del programa me reportó el problema, que, yo también tenía, sin llegar nunca a un "out of memory" como en su caso. Ahora parece que el problema está solucionado, aunque, como vemos, hay que tocar algunas cosas como los componentes de "EmbeddedWB" (que yo uso en mi programa) y hasta la VCL... que es la primera vez que toco en todos estos años trabajando con Delphi. Jamás había tenido que tocar nada de la VCL hasta hoy. En fin, cualquier otro comentario será bienvenido, pero, vuelvo a darte las gracias por tu estupenda respuesta Al. |
|
|
Temas Similares | ||||
Tema | Autor | Foro | Respuestas | Último mensaje |
Actualizar a Delphi XE desde cualquier versión de Delphi (hasta fin de mes) | rrf | Varios | 0 | 11-03-2011 17:12:05 |
que tan cierto es que el 25 salio delphi 2009 | gloriamab30 | Noticias | 1 | 05-09-2008 23:55:31 |
(Corregido) Introduccion a InstantObjects | Ezecool | OOP | 0 | 05-07-2007 22:37:16 |
Problema con Versión 10 de Indys | AGAG4 | Internet | 4 | 01-02-2006 16:50:27 |
Ejecutar aplicacion delphi cada cierto tiempo | mgaray | API de Windows | 9 | 28-01-2005 19:16:20 |
|