![]() |
![]() |
| Paypal | FTP | CCD | Buscar | Trucos | Trabajo | Foros |
|
|||||||
| Registrarse | FAQ | Miembros | Calendario | Guía de estilo | Temas de Hoy |
![]() |
|
|
Herramientas | Buscar en Tema | Desplegado |
|
|
|
#1
|
||||
|
||||
|
Hola a todos,
estoy haciendo una clase que trata de mantener listas de Claves/Valor (siendo Valor, un record de 2 campos). Envío la clase entera (no es muy grande) junto con una indicación del lugar donde se produce el Invalid Pointer (buscar ERROR). Seguir leyendo al final del código de la clase (adjunto test donde se produce el error).
Dejo también el conjunto de Tests (usando DUnit framework) que estoy utilizando para probar la clase. El error se produce en el método TearDown del TestCase. Es decir, en la destrucción de la clase objeto del Test. Lo malo del asunto es que solo se produce en la ejecución del TearDown para el test: TestDelColumnaStandAlone (Como podreis comprobar si ejecutais el TestCase).
En este momento lo tengo funcionando correctamente, ya que he modificado la clase para usar un TList en lugar de un Array dinámico. Pero tengo una enorme curiosidad por saber que estaba haciendo mal. Seguro que es muy evidente. El método: DelColumna que es el que genera el error (eso creo), pretende que se pueda borrar una "columna", y ajustar el resto de forma consecutiva. Es decir, si tengo 3 columnas (0, 1 y 2) y borramos la columna 0 (DelColumna(0)), las columnas deberían quedar: 2 columnas = (0,1) ..... siendo estas 0 y 1, las antiguas 1 y 2. Bueno, gracias..... |
|
#2
|
|||
|
|||
|
Hola,
creo que es debido a esto :
De todas maneras, es mucho codigo para analizarlo detalladamente ahora saludos.PD : mirando un poco mas...
no deberias asignar directamente? (Columna[x] := Columna[x+1]) sin el create, me refiero. De la manera que lo estas haciendo estas creando otra columna, o sea, que el antiguo puntero se pierde. PDD : y mirandolo aun un rato mas : deberias no usar el free, sino hacer asignacion directa i liberar tansolo el ultimo.
Creo que asi te funcionaria. De la manera que lo hacias, creabas una columna (x+1) cuya propietaria era Columna(x), que acababas de liberar...(en teoria te tendria que petar tambien aqui, pues creas mediante columnas(index) que acababas de liberar ), por lo que te quedaba la columna(index) sin asignar, aunque las demas estuviesen bien. Por tanto, en el destroy te debia petar en el indice que se habia llamado con delcolumn. Un saludo.Última edición por coso fecha: 16-01-2011 a las 20:11:20. |
|
#3
|
||||
|
||||
|
Hola Coso, ante todo, muchas gracias por dedicar tu tiempo......
Cita:
Explico el motivo: Justo antes del bucle FOR, lo primero que hago es liberar el objeto TDictionary ( Columna[index] ). Con lo que el nuevo Create, no debería dejar un objeto sin liberar (un Memory Leak). Cada elemento del Array, en su forma Columna[x] referencia a cada uno de los objetos-lista genericos: TDictionary<>. Según creo, la creación de una columna, pasando otra como parámetro debería hacer lo siguiente (en teoría): 1.- Crear una columna nueva (un nuevo objeto TDictionary, sin valores). 2.- Copiar los valores de la columna x+1 (un TDictionary) a la nueva columna x. Y digo copiar, no referenciar al otro objeto TDictionary. Cita:
Siempre en teoria, claro. :-) Con el código que indicas, creo que sucedería lo siguiente. Partiendo de esta situación hipotética de ejemplo: Columna[0] = TDictionary con Pointer: 1000. Columna[1] = TDictionary con Pointer: 1001. Columna[2] = TDictionary con Pointer: 1002. Siguiendo el bucle que expones y suponiendo que borramos la número 0, quedaría así: Columna[0] = 1001 Columna[1] = 1002 Y liberamos el objeto que apunta a 1002 (la Columna[2]), con lo que yo creo que tenemos: 1.- Un memory leak para el objeto que estaba en 1000 (pues no se ha liberado). 2.- Un invalid Pointer en cuanto queramos acceder a Columna[1], pues el objeto que estaba en 1002, ha sido liberado. Pero claro.... todo esto, insisto, es lo que yo creo. Muchas gracias Coso.... :-) Última edición por yapt fecha: 16-01-2011 a las 20:34:11. Razón: Clarificación. |
|
#4
|
||||
|
||||
|
Tu codigo tiene muchos errores por varios lados.
Para eliminar varios al mismo tiempo te aconsejo utilizar la clase TList en vez de array dinámico. Por otro lado al asignar los elementos tienes:
aca lo que estas haciendo es crear el objeto TColumnaDict asignarle valores y agregarlo a FColMant, hasta aca todo bien, pero luego lo destruyes !!! Tienes que entender que Delphi al pasar objetos como parametros no crea una nueva instacia (copia) de ellos, sino solamente pasa el puntero, por lo que el objeto sigue siendo el mismo, asi que al destruirlo, destruiste el objeto que pasaste. Donde obtienes el error es porque intentas de volver a destruir el objeto ya destruido
__________________
[Crandel] |
|
#5
|
||||
|
||||
|
Cita:
Agradecería, no obstante, saber cuales son esos errores. ![]() Cita:
FColMant.AddColumna(Value); Este paso, copia la Colección a la nueva colección que se crea internamente, dentro de la clase. Cita:
Pero debo insistir, el "truco" de esta clase está en:
Donde la segunda forma de crear el objeto TColumnaDict, realiza una copia del objeto Value. Si fuese de otro modo, en el test, el método:
No funcionaría. Y si habeís pasado el test, todos ellos funcionan con normalidad (y he comprobado que sin ningún Memory Leak), excepto el método del TestCase: y por tanto, el método de la clase:
Gracias por la respuesta.. ![]() Un saludo. Última edición por yapt fecha: 17-01-2011 a las 08:58:18. Razón: Aclaración y corrección |
|
#6
|
|||
|
|||
|
Cierto, pense lo de mover los valores unicamente como si fuese un array simple. Gracias por la correcion.
Entonces deberia ser algo asi no?
esto es, sin tener que recrear todo el array dentro del bucle, sino unicamente moviendo los ya existentes. Creo que ahora si es correcto... PD: remirando tu codigo y habiendo leido lo que dices del create de TDictionary, creo que el error lo tienes en la linea del mismo. No se bien bien como va, pero me extraña que esta expresion (Columna[x].Create( Columna[x+1] )) funcione. No estas asignando nada a nada, solo llamando al create 'al aire', digamos, sin que se recoja su resultado (de todas maneras le echare un vistazo a la clase TDictionary). Si pruebas Columna[x] := TColumna.Create(Columna[x+1]) te falla tambien? Saludos. Última edición por coso fecha: 17-01-2011 a las 13:14:11. |
|
#7
|
||||
|
||||
|
Coso ya encontró tu error asi que no hay mucho mas para dar vuelta, pero igual intento de explicar mejor a lo que me refería.
Cita:
El proceso de creación de un objeto aunque es muy fácil para nosotros implementarlo es preferible no abusar de él. Ya que no solo consume mayor tiempo de ejecución sino que también el hecho de crear/borrar puede provocarte fragmentación de la memoria. Es por eso que te recomendaba el uso la clase TList, hace exactamente lo que necesitas hacer pero ya optimizado por la gente de Delphi.
__________________
[Crandel] |
![]() |
|
|
Temas Similares
|
||||
| Tema | Autor | Foro | Respuestas | Último mensaje |
| Invalid Pointer Operation | FerCastro | Varios | 3 | 23-02-2010 21:47:26 |
| Invalid Pointer operation Dll | mcarazas | Varios | 2 | 15-10-2008 21:45:14 |
| Invalid Pointer operation Dll | mcarazas | Varios | 0 | 15-10-2008 16:42:23 |
| invalid pointer operation | muppett | Varios | 1 | 05-03-2008 00:17:55 |
| QR - Invalid Pointer Operation | alapaco | OOP | 6 | 07-06-2006 22:43:31 |
|