Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   C++ Builder (https://www.clubdelphi.com/foros/forumdisplay.php?f=13)
-   -   Problema (o eso creo) con vectores dinamicos (https://www.clubdelphi.com/foros/showthread.php?t=62752)

NEG1414 12-01-2009 20:17:29

Problema (o eso creo) con vectores dinamicos
 
Buenas haber si me doy Explicado

Tengo dos Formularios Uno Principal y otro Secundario.Desde el formulario Principal accedo
al Secundario de forma modal pasando por referencia un Objeto que contiene varios atributos:


Código:

TObjeto PasObjeto;

LlamaForm = new TFormSecundario(this,*PasObjeto);

//Mostramos el Formulario como modal
switch (LlamaForm->ShowModal())
{
case mrOk:
break;
case mrCancel:
break;
}

delete LLamaForm;


En el Formulario Secundario creo como atributos Globales varios vectores dinamicos:
y asigno el Objeto que paso a un atributo del Mismo Tipo

Código:
class TFormSecundario : public TForm
{
private:

TObjeto *PssObj

TStringList *Vector1;
AnsiString *Vector2;
short *Vector3;
char *Vector4 ;
.................................

public:

__fastcall TFormSecundario(TComponent* Owner,TObjeto &PO);

}

__fastcall TFormSecundario(TComponent* Owner,TObjeto &PO);
{
PssObj = &PO
}

Tanto el Objeto "Pasado" como los vectores ( los inicializo en el Evento FormActivate) operan perfectamente
una vez salgo del FormSecundario Elimino todos vectores y regreso al FormPrincipal.

Código:
delete Vector1;
delete Vector2;
....

Modalresult= Ok

Y es aqui cuando surge el problema al acceder de nuevo desde el FormPrincipal al Secundario
me da el siguiente error

Acces Violation at address XXXXXXX in module Vcl60.bpl

He probado varias cosas y he comprobado que a medida que convierto los vectores dinamicos en fijos me permite acceder
mas veces seguidas al Formulario Secundario sin darme error... Me Explico:
Si convierto AnsiString *Vector2; en AnsiString Vector[20];
me permite acceder 3 veces al Form antes de darme el error
Si tambien convierto short *Vector3; en short Vector{20];
me permite acceder 7 veces seguidas antes de darme el error
y asi sucesivamente.

Alguna Idea Gracias

Nota: Se que ese error se suele dar cuando no se Inicializa algun Objeto
o cuando se declara un vector dinamico no se inicializa y sin embargo se
utiliza, creo que no es el caso.

escafandra 12-01-2009 22:01:21

Una clase con punteros potencialmente puede dar problemas. Tenemos que ser muy cuidadosos con su uso.

Deben ser creados y destruidos. No normal es crearlos en el constructor de la clase y destruirlos en el destructor. Si se asigna dinamicamente nuevos valores también deben destruirse previamente a la asignación dinámica.

Ten en cuenta que al hacer delete LLamaForm; lo que haces es llamar al destructor de la clase
Código:

TFormSecundario:: ~TFormSecundario();
En toda clase que tenga punteros debe implementarse un destructor que los destruya si la asignación fue dinámica.

Resumiendo, lo normal es hacer la asignación dinámica en el constructor, no en OnCreate y la destrucción en el destructor, no en OnDestroy, Esta es la forma de operar en C++. Otras formas pueden funcionar, si se hacen con cuidado, pero piensa que lo primero que se ejecuta al crear un objeto de una clase en C++ es el constructor con el que se crea, y lo último, el destructor.

Otra cosa, en tu código TObjeto *PssObj le asignas tras una referencia, espero que sea un error de transcripción. Asegúrate que el puntero asignado realmente existe en cada llamada....
Código:

__fastcall TFormSecundario::TFormSecundario(TComponent* Owner,TObjeto  &PO): TForm(Owner)
{
  PssObj = &PO // ???? Porqué no pasas directamente un puntero a TObjeto
  .... Inicialización de punteros dinámicos.....
  Vector1 = new ...
  .......
}

__fastcall TFormSecundario::~TFormSecundario()
{
  delete Vector1;
  delete Vector2;
  ....
}


Saludos.

NEG1414 13-01-2009 14:00:37

En primer lugar gracias por contestarme

He tomado en cuenta tus consideraciones y he inicializado los vectores dinamicos en el constructor y he creado ademas un metodo destructor donde los elimino.La verdad es que Ahora parece que funciona mejor pero sigue dando un error....

el error lo produce el siguiente vector


AnsiString *VectorErroneo


// (en el constructor)
VectorErroneo = new AnsiString[30]

//En otro procedimiento
for (int i=0;i<25;i++)
{
VectorErroneo= NULL;
}


Opero perfectamente con el Vector Pero Al salir del FomSecundario me da el siguiente error

Acces Violation at address XXXXXXX in module ´BORLNDMM.DLL'

!!! solo si añado la sentencia delete Equipos !!!

El vector es del tipo AnsiString y no se si requiere alguna considracion especial.El caso es que si Elimino la linea delete Equipos del destructor lo demas me funciona perfectamente.

gracias

PosData: No entiendo lo de

PssObj = &PO // ???? Porqué no pasas directamente un puntero a TObjeto

Trabajo con el Objeto PssObj (que se supone apunta a la direccion de PasObjeto)
En FornSecundario modifico los atributos del Objeto referenciado
y al salir del formulario me conserva las modificaciones en PasObjeto)

escafandra 13-01-2009 15:05:04

Cita:

Empezado por NEG1414 (Mensaje 334302)
AnsiString *VectorErroneo

// (en el constructor)
VectorErroneo = new AnsiString[30]

//En otro procedimiento
for (int i=0;i<25;i++)
{
VectorErroneo= NULL;
}

Ten en cuenta que si dejas punteros sin destruir, consumen recursos de memoria. Si destruyes un puntero ya destruido, tendrás un error, puesto que su valor, y por tanto la dirección a la que apunta, no cambia tras la destrucción. Cuando creamos y destruimos punteros fuera del constructor y destructor, es una buena práctica inicializarlos a 0 cuando no se han creado para luego darles otro valor con el operador new. Así puedes detectar si un puntero apunta a una dirección válida.

Para inicializar un AnsiString a cadena nula es así:
Código:

AnsiString Cadena = "";
Si Tenemos un puntero AnsiString:
Código:

AnsiString *pCadena = new AnsiString;
*pCadena = "";

Para crear un array de AnsiString tienes la opción de usar un TStringList.

Código:

MyClase::MyClase(){
  Tipo* Vector = 0;
  CrearVector();
}

MyClase:: CrearVector()
{
  if(Vector) delete Vector;
  Vector = new Tipo;
}

MyClase::~MyClase(){
  if(Vector) delete Vector;
}

Cita:

Empezado por NEG1414 (Mensaje 334302)
No entiendo lo de

PssObj = &PO // ???? Porqué no pasas directamente un puntero a TObjeto

Código:

__fastcall TFormSecundario::TFormSecundario(TComponent* Owner,TObjeto* PO): TForm(Owner)
{
  PssObj = PO;
.......
}

Saludos.


La franja horaria es GMT +2. Ahora son las 18:03:16.

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