PDA

Ver la Versión Completa : Imposible.. no encuentro el error


NEG1414
31-07-2013, 19:02:25
Buenas..

LLevo varios dias intentando encontrar el porque de un error (el valor de una variable varia al inicializar una clase sin razon aparente).... y me es imposible ... He reducido a la minima expresion el codigo y que siga dando el problema para hacerlo mas comprensible.

Class TClase1
{
private :
TStringList *Lista;
public :
TClase1();
{
Lista = new TStringList;
}
}


Class TClase2 (#Include "Clase1.h")
{
private:
TClase1 ClaseHija;
public:
TClase2()
{
struct ffblk ffblk; //Obiamente en el programa original se lee un archivo en esta version reducida solo incluyo esta linea
suficiente para hacer saltar el error
}

}

class TDatos
{
private:

struct SRegistro
{
bool a;
bool b;
unsigned short Num;
};

typedef SRegistro TRegistro

struct SArchivo
{
char Nombre [16];
TRegistro ListaRegistros [100];
};


typedef SArchivo TArchivo;

public:

typedef SArchivo TArch;
TDatos()
{
}

TDatos::Archivo *TDatos::LeerDatos()
{
TDatos A;
A.ListaRegistro[12].a = true
A.ListaRegistro[12].b = false;
A.ListaRegistro[12].Num = 0;

return &A
}


PROGRAMA PRINCIPAL

#Include Clase2
#Include Datos
......
.....
TDatos *BDatos = new TDatos();
TDatos::TArch LeLosDatos;
LeLosDatos = BDatos->LeerDatos();

TClase2 *ClaseSegunda = new TClase2()
Una vez Leidos, los datos obtenidos son los correctos

LeLosDatos.ListaRegistro[12].a = true
LeLosDatos.ListaRegistro[12].b = false;
LeLosDatos.ListaRegistro[12].Num = 0;

El problema surge cuando inicializo ClaseSegunda.. los Valores de LeLosDatos se modifican sin razon aparente.

He comprobado que:

- Si Elimino de Clase 1 el TStringList *Lista NO DA ERROR
- Si elimino de Clase1 en el Constructor struct ffblk ffblk NO DA ERROR
- Si en la estructura struct SArchivo de Tclase2 sustituyo TRegistro ListaRegistros [100];
por TRegistro ListaRegistros; NO DA ERROR

Supongo que es error al declarar punteros o estructuras que solapan posiciones de memoria pero no lo veo NECESITO AYUDA..

Gracias





}

ecfisa
01-08-2013, 08:26:02
Hola NEG1414.

No estoy seguro de haber entendido el problema, pero hice una prueba simple con algunas modificaciónes (respetando la esencia que entendí del código) y luego de instanciada TClase2 visualizo sin cambios los valores asignados.

Y realmente en la porción de código de tu mensaje no veo de que modo la clase TClase2 pudiera estar induciendo cambios en la clase TDatos...

De todas formas te pongo la prueba por si pudiera servirte de ayuda:

...
#include <dir.h>

class TClase1 {
private:
TStringList* Lista;
public:
TClase1() { Lista = new TStringList; }
};

class TClase2 : public TClase1 {
private:
TClase1 ClaseHija;
public:
TClase2 () { struct ffblk ffblk; }
};

class TDatos {
private:
struct SRegistro {
char a, b, c;
unsigned short Num;
};
typedef SRegistro TRegistro;

struct SArchivo {
char Nombre[16];
TRegistro ListaRegistros[100];
};
typedef SArchivo TArchivo;

public:
typedef SArchivo TArch;
TDatos(){ }
TDatos::SArchivo* TDatos::LeerDatos() {
TArch A;
// Asignar unos valores para visualizar
strcpy(A.Nombre, "UN NOMBRE");
A.ListaRegistros[0].a = 'X';
A.ListaRegistros[0].b = 'Y';
A.ListaRegistros[0].c = 'Z';
A.ListaRegistros[0].Num = 115;
return &A;
}
};

void __fastcall TForm1::Button1Click(TObject *Sender)
{
TDatos* BDatos = new TDatos();
TDatos::TArch LeLosDatos;

LeLosDatos = *BDatos->LeerDatos();
Memo1->Clear();
Memo1->Lines->Add("Antes de instanciar Clase2\n");
Memo1->Lines->Add(LeLosDatos.Nombre);
Memo1->Lines->Add(LeLosDatos.ListaRegistros[0].a);
Memo1->Lines->Add(LeLosDatos.ListaRegistros[0].b);
Memo1->Lines->Add(LeLosDatos.ListaRegistros[0].c);
Memo1->Lines->Add(IntToStr(LeLosDatos.ListaRegistros[0].Num));
Memo1->Lines->Add("\n--------------------------");

TClase2 *ClaseSegunda = new TClase2();

Memo1->Lines->Add("Luego de instanciar Clase2\n");
Memo1->Lines->Add(LeLosDatos.Nombre);
Memo1->Lines->Add(LeLosDatos.ListaRegistros[0].a);
Memo1->Lines->Add(LeLosDatos.ListaRegistros[0].b);
Memo1->Lines->Add(LeLosDatos.ListaRegistros[0].c);
Memo1->Lines->Add(IntToStr(LeLosDatos.ListaRegistros[0].Num));
}


Saludos :)

NEG1414
01-08-2013, 11:32:17
Gracias por contestarme...

Muestro la direccion de donde bajar el programa ejecutable (Uloerror) para facilitar la compresion del problema..

https://app.box.com/s/bni8bvn20e4zdzgz67f4

Gracias Otra Vez.

ecfisa
02-08-2013, 05:52:01
Hola NEG1414.

Lo siento, intenté compilar el código para probarlo pero aparentemente me falta el package LDM70SE_B6.BPI:

[C++ Warning] PRINCIPAL.cpp(54): W8004 'Clas2' is assigned a value that is never used
[C++ Warning] Datos.cpp(37): W8075 Suspicious pointer conversion
[Linker Fatal Error] Fatal: Unable to open file 'LMD70SE_B6.BPI'


Saludos. :)

NEG1414
02-08-2013, 16:14:35
Gracias por contestar (eres mi ultima esperanza) Mando la direccion de donde bajar el ejecutable limpio de polvo y paja .... compilado sin ningun paquete adicional...

https://app.box.com/s/uva20447qs27q9ts5o1o

Gracias otra vez...

escafandra
02-08-2013, 20:07:59
Si me permitís, NEG1414 fíjate en este fragmento de tu código:


TDatos::TArchivo *TDatos::LeoDatos()
{

TArchivo A;


for(int i=0;i<100;i++)
{
A.ListaRegistros[12].Primero = true;
A.ListaRegistros[12].Segundo = false;
A.ListaRegistros[12].Num = 0;
}

return &A;

}


Creas una variable local, la modificas y devuelves un puntero a la misma. Al salir de la función esa variable deja de existir, luego el puntero devuelto apunta a un valor inválido.

Creo que lo que pretendes es que la variable A sea de la clase y no de la función, en cuyo caso declarala como miembro de la clase TDatos. En oreo caso incorporalá como parámetro de la función LeoDatos().

Con estos cambios que te pongo debajo, funciona como creo que quieres:

class TDatos
{
private:


struct ERegistro
{
bool Primero;
bool Segundo;
unsigned short Num;
};

typedef ERegistro TRegistro;

struct SArchivo
{
char Nom[16];
TRegistro ListaRegistros[100];
} Archivo; // DECLARO VARIABLE Archivo

typedef SArchivo TArchivo;


public:

typedef SArchivo TArch;

//Constructores
TDatos();

TArchivo *LeoDatos();

};


TDatos::TArchivo *TDatos::LeoDatos()
{
for(int i=0;i<100;i++)
{
Archivo.ListaRegistros[12].Primero = true;
Archivo.ListaRegistros[12].Segundo = false;
Archivo.ListaRegistros[12].Num = 0;
}

return &Archivo;
}


Permíteme un consejo, clarifica un poco la estructura de tu código y no abuses de typedef



Saludos.

NEG1414
03-08-2013, 10:53:05
Muchisimas gracias a los dos por atenderme....

Escafandra (Master) con tu explicacion he entendido donde esta el problema, la verdad es que los punteros siempre se me han atascascado...

Gracias otra vez..

Nota: tomare en cuenta tus consejos