C/Visual C - duda con punteros

 
Vista:

duda con punteros

Publicado por Nelek (816 intervenciones) el 27/02/2007 16:26:04
Hola,

Son iguales estas expresiones?

CMyObject* pTemp = new CMyObject;
*pObj = pDoc->FindNamed (m_szSelName);
if (pObj->m_szName != "")
//Hago lo que me interesa

y

CMyObject* pTemp = new CMyObject;
pObj = &pDoc->FindNamed (m_szSelName);
if (pObj->m_szName != "")
//Hago lo que me interesa

Mi objetivo es poder modificar el parametro de uno de mis objetos, que esta guardado en una lista de dichos objetos dentro del documento, pero SIN traerme el objeto en si. Por eso estoy trabajando por punteros y referencias, pero aun no me aclaro del todo con ellos.

La funcion que busca es:

CMyObject& CMyDoc::FindNamed(const CString szName)
{
CMyObject* roEmpty = new CMyObject;
//Si la lista esta vacia devuelvo uno vacio.
if (m_cmlObjectSet.IsEmpty ())
return *roEmpty;

POSITION pos= m_cmlObjectSet.GetHeadPosition ();
while (posReg)
{
CMyObject tempObj = m_cmlObjectSet.GetNext (pos);

//Si encuentro el nombre que busco, devuelvo el objeto (GetPrev porque pos ya apunta al
//siguiente)
if ((tempObj.m_szName == szName) && (pos != NULL))
return m_cmlObjectSet.GetPrev (pos);

//Si encuentro el que quiero y es el ultimo de la lista
else if ((tempObj.m_szName == szName) && (pos == NULL))
return m_cmlObjectSet.GetTail ();
}

// Si no lo encuentro, devuelvo vacio
return *roEmpty;
}

Nota:
En el constructor de CMyObject inicializo: m_szName = ""; por eso luego pregunto si esta asi para ver si me ha devuelto el objeto vacio y diferenciar del objeto de la lista.

-----------

Fallos no me da al compilar, pero sin embargo no me funciona bien. :S

Se supone que al poner un return por una referencia en mi funcion de busqueda el propio compilador toma la variante TYPE& GetPrev (pos) y TYPE& GetTail () que pone en la documentacion, no?

Acepto cualquier tipo de mejora, sugerencia, consejo... Gracias
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder

Fallo tipografico en funcion

Publicado por Nelek (816 intervenciones) el 27/02/2007 16:32:32
Me he equivocado al reescribir la funcion.

Deberia ser:
while (pos)

y no:
while (posReg)

En el programa concuerda, asi que ese no es el fallo. Como dije, no tengo fallos de compilacion, pero al ejecutar no me funciona bien. Y no se si el fallo esta al buscar... al traer... o donde...
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

La duda sigue.

Publicado por Nelek (816 intervenciones) el 28/02/2007 08:17:49
Hola,

pos si las moscas. No sea que a causa del mensaje "fallo tipografico encontrado" se sobreentienda que ya funciona. No es así.

El mensaje de arriba del todo con el mismo titulo es porque me equivoque y, en lugar de escribir aqui, puse un mensaje nuevo
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:duda con punteros

Publicado por fernando.gomez (1603 intervenciones) el 01/03/2007 03:26:49
No, definitivamente no son lo mismo. Podrían tener el mismo comportamiento, pero eso depende de cómo esté definida CMyObject. Me explico.

*pObj = pDoc->FindNamed (m_szSelName);

Aquí, pObj apunta a una dirección de memoria X y haces que esa memoria X ahora tenga un nuevo objeto (es decir, se copia a la dirección X).

pObj = &pDoc->FindNamed (m_szSelName);

Aquí, lo que haces es que pObj apunte a una dirección de memoria diferente.

Peeeero en escencia tendrías el mismo resultado.

Ahora, me llama la atención esta línea:

if (pObj->m_szName != "")

La notación húngara sugiere que m_szName es un array de caracteres (TCHAR*). Por lo que no puedes hacer esa comparación m_szName != "". Ahora, que si es un CString, pues vale. No puedes comparar TCHAR*, char*, wchar_t* etc, porque hará comparaciones a nivel de dirección de memoria, y eso el 99.9999% de las veces es FALSE. Emplea strcmp, wstrcmp o _tcscmp.

Saludos.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:duda con punteros

Publicado por Nelek (816 intervenciones) el 01/03/2007 08:17:53
Hola fernando, gracias por la respuesta.

Lo que intento hacer es, en VC++ 6, acceder al elemento de una lista que tengo en el documento. La definicion de la lista es CMyList <CMyObject, CMyObject&> m_clMyList. El nombre del elemento es un CString, por eso lo he usado asi.

Lo quiero hacer es acceder al elemento que me interesa desde la CView, pero sin tener que traerme el objeto en si. Por eso intento usar los punteros y las referencias. La funcion, que uso para acceder a el, la he modificado porque estaba mal planteada. La nueva version es:

CMyObject& CMyDoc::FindNamed(const CString szName)
{
CMyObject* pEmptyObj = new CMyObject;
POSITION pos = m_clMyList.GetHeadPosition ();
while (pos)
{
CMyObject* pTempObj = &m_clMyList.GetNext (pos);
if (pTempObj->m_szName == szName)
return *pTempObj;
}

return *pEmptyObj;
}

Y me funciona, en cuanto al acceso al elemento se refiere. Consigo modificar la variable miembro que me interesa y luego acceder a ella en otra funcion de la vista. El problema que tengo ahora son los "memory leaks" ya que estoy creando punteros a objetos vacíos a cada pasada (y da la casualidad que he de usar dicha funcion en el OnDraw, o sea que hay muchisimas llamadas). Lo que no se es como hacer para liberar la memoria y evitar el problema ya que el propio puntero (al objeto vacio o al objeto de la lista que me interesa) es el valor de retorno y una vez se ejecuta el return ya no puedo poner los "delete" detras.

He intentado definir los punteros que tengo que usar ciclicamente como miembros del Documento y luego en el OnCloseDocument liberarlos, pero no me funciona, ni con "delete" ni con "free".

Que me aconsejais? Funcionaria el hacer la liberacion en una funcion aparte y llamarla justo despues de cada llamada a la que tengo aqui arriba? Me refiero a algo como (teniendo el puntero al objeto vacio como miembro del documento):
CMyObject* pObj = &FindNamed (m_szSelName);
pDoc->FreeObjPointers ();

Donde:
void CMyDoc::FreeObjPointers ( )
{
delete m_pEmptyObj;
}

O como seria la mejor opcion? La verdad es que el tema de punteros es mas complicado de lo que yo creia :S
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Solucionado en gran medida (solo falta 1 cosilla)

Publicado por Nelek (816 intervenciones) el 01/03/2007 10:18:04
Hola,

a los que os haya interesado este hilo... He logrado solucionar casi todo replanteandome el asunto. En lugar de devolver punteros y demas... y tener los problemas de los memory leaks proporcionales al tiempo de ejecucion del programa y el numero de elementos utilizados (por lo que comente en el mensaje de arriba)... Ahora la cosa se ha reducido a 3 memory leaks fijos, que no logro quitarlos, uno por puntero que uso.

Lo que he hecho es:
-------- Definirme los punteros a los tres tipos de objetos como miembros publicos del Documento
CMyObjet1* m_pObject1; CMyObjet2* m_pObject2; CMyObjet3* m_pObject3;

-------- Dichos punteros, los relaciono con su tipo de elemento al inicializar el documento en CMyDoc::OnNewDocument ()
m_pObjectX = new CMyObjectX;

-------- Modificar la funcion de encontrar el objeto segun el nombre dejandola en:
void CFPSDoc::FindInNamed(const CString szName)
{
m_pObject = NULL; //Iniciamos a NULL para evitar valores residuales
POSITION pos = m_clMyList.GetHeadPosition ();
while (pos)
{
m_pObject = &m_clMyList.GetNext (pos); //Voy buscando
if (m_pObject->m_szInName == szName) //Si lo encuentro, apunto al elemento
return;
}
m_pObject = NULL; //Si no encuentro el elemento, no apunto a nada
}

-------- Alla donde antes hacia la llamada y la comprobacion
pObj = &pDoc->FindNamed (m_szSelName);
if (pObj->m_szName != "")

ahora hago

pDoc->FindInNamed (m_szSelName);
if (pDoc->m_pObject != NULL)

Supongo que tendre que meter los punteros m_pObjectX en el serialize para no tener problemas con el OnOpenDocument, me equivoco?????? pero lo hare como NULL.

Con estas modificaciones funciona como yo queria, lo unico que me queda es... Como diantres quito de en medio los 3 memory leaks de la inicializacion en el OnNewDocument? He intentado poniendo "delete m_pObjectX" y "free (m_pObjectX)" dentro del OnCloseDocument y una de dos, o no hace nada y me quedo igualmente con los 3 leaks, o me salta un MessageBox diciendo que "Punto de interrupcion definido por el usuario llamado desde el codigo por 0x7C911239", el debugger me dice en su ultima linea "HEAP[FPSII.exe]: Invalid Address specified to RtlValidateHeap( 00320000, 003278AC )" y la pantalla del codigo salta al ensamblador en la linea:
7C91122F nop
7C911230 int 3 <---- AQUI
7C911231 ret

Tambien he probado a poner los delete y los free en el void CMyView::OnDestroy()
y ahi lo que hace es lanzarme assertions. Creo que la razon es porque el documento se destruye antes que la View, por eso cuando intento acceder con el CMyDoc* pDoc = GetDocument (); para poder borrar los elementos... con "delete pDoc->m_pObjectX" me dice que una leche.

Asi que de momento, me voy a quedar con los 3 memory leaks de los punteros no liberado. Espero que alguien me pueda dar una solucion y si no... "solo" son 3 ;) :P
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

Solucionado

Publicado por Nelek (816 intervenciones) el 01/03/2007 10:46:18
Hola,

dicen que el español piensa bien... pero TARDE. Al final he logrado quitar los memory leaks con la solucion mas simple de todas.

En la inicializacion, en lugar de poner
m_pObject1 = new CMyObject1;

es tan simple como poner:
m_pObject1 = NULL;

Siento la acumulacion de mensajes.

Por que será que lo mas evidente es lo que mas se esconde???
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar