Variable pierde valor

Iniciado por Kaxperday, 8 Julio 2015, 15:35 PM

0 Miembros y 1 Visitante están viendo este tema.

Kaxperday

Hola a todos, miren tengo la siguiente clase:

Código (cpp) [Seleccionar]
struct host
{
u_char ip[4];
u_char mac[6];
};

class lista_usuarios
{
public:
vector<host> usuarios;
void insertar_host(u_char* ip, u_char* mac);
};


Tiene un vector de estructuras como se puede observar. Claro, ¿cómo hago para reservar memoria dinamica si tiene un vector que desconozco cuanto puede llegar a valer?

Declaración de un puntero de tipo clase lista_usuarios:

Código (cpp) [Seleccionar]

lista_usuarios* buscar_usuarios()
{
lista_usuarios *lista_host = nullptr;
printf("ANTES: %d\n", lista_host->usuarios.size());
auto envio_arp = async(enviando_arp, capturador, ip_cliente, mac_adaptador, ip_gateway);
auto recojo_arp = async(recogiendo_arp, capturador, *lista_host);

envio_arp.get();
recojo_arp.get();

printf("\nDESPUES: %d\n", lista_host->usuarios.size());
return lista_host;


Como se puede observar la paso como parámetro a la función recogiendo_arp.
En esa clase se añadirán estructuras de tipo host a la lista de hosts de lista_usuarios, con su mac e ip, se incrustarán.

El problema es que la lista me debería de salir que tiene 6 hosts y me dice que tiene 0, los valores se pierden.

Código (cpp) [Seleccionar]
void recogiendo_arp(pcap_t *capturador, lista_usuarios lista)
{lista.insertar_host(ip, mac);}


El problema es que tras llamar a la funcion y añadir host a el vector de lista_host de lista_usuarios, me dice que el vector lista_host tiene 0 elementos, cuando he podido comprobar que se añaden hasta 6.

Saludos.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

Eleкtro

#1
No se absolutamente nada de C++ así que no se si esto te ayudará, pero a simple vista me parece que hay una o dos cosas incorrectas... ¿no tendrías que pasarle la variable cómo referencia utilizando el operator "&" para poder modificar el estado de dicha variable de forma permanente, en lugar de pasarle una simple copia de la variable al método que estás llamando cómo creo que estás haciendo?.

Reference Parameters in C++

Aparte de eso, imagino que estarás esperando a que la operación asíncrona (deduzco que async() debe hacer algo de manera asíncrona) haya finalizado de modificar el estado de la variable antes de usar la referencia para comprobar si tiene un nuevo valor, ¿verdad?.

Saludos








Kaxperday

#2
Hola elektro gracias por la respuesta, pues he probado también a pasarlo como doble puntero (con el operador &), y el resultado era el mismo. Respecto a lo de async cuando llamo a el metodo get(), se supone que la siguiente intrucción no se ejecuta hasta que haya acabado esa. Son instrucciones que a lo sumo tardan 5 segundos ambas, cuando acaban me muestra lo de "DESPUES: .." ahí debería ponerme el numero de elementos de la lista que no puede ser 0 pues acabo de añadir 6 (ips y sus asociadas macs de la red XD).

Edito: He probado muchas cosas, y no se a cual me refería de todas XD, aquí he puesto la lista como un puntero, pero también he probado otras 2 opciones más que es como variable normal (pasandola sin más a recogiendo_arp) y devolviendola como &lista_host.

Y otra opción que es la que decía elektro, declarando un puntero y pasandoselo como doble puntero a la funcion recogiendo_arp.

Las 3 han fallado, el problema creo que es de asignación de memoria, pues cuando sale de recogiendo_arp pierde los valores que añadió allí, he probado también a reservarla memoria al puntero con malloc(sizeof(lista_usuarios)), pero lista_usuarios tiene vectores dinamicos, entonces no sé cuanta memoria debería reservar.

Saludos.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

ivancea96

Cuando uses async() o threads, no olvides manejar variables con mutec u otro tipo de controlador. Especialmente si andas con clases o estructuras. Y más especialmente si andas con punteros.

Kaxperday

Desconozco eso de mutex aún no se como se usa, pero lo tendré en cuenta más adelante, supongo que te referirás a una variable de control para que salga de la funcion del thread o del async, una variable volatile solía utilizar para hacerlos salir.

En este caso no hay problema pues al enviar paquetes se envía un numero definido de ellos y al recibir salgo del bucle por un contador temporal, cuando llamo a los get me aseguro de que hallan acabado y de hecho lo hacen, la siguiente instruccion que es un printf ya se ejecuta cuando ambos async han acabado.

Luego no veo porque pueda influir en el contenido del puntero  :-\ :-\

Saludos.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

ivancea96

Mutex -> Mutual Exclusion

Sirve para evitar que 2 threads ejecuten una misma parte de código a la vez. Si 2 threads se meten en los métodos de tu lista a la vez, puede acabar dando problemas. No digo que esté ocurriendo, pero tenlo en cuenta. Threads o async() sin mutex u otro formato de control, es muy peligroso para la integridad del ejecutable.

Kaxperday

#6
Vale lo tendré en cuenta. He probado a eliminar un async el de recibir arps y pasa igual:

Código (cpp) [Seleccionar]
lista_usuarios* buscar_usuarios()
{
static lista_usuarios lista_host;
printf("ANTES: %d\n", lista_host.usuarios.size());
auto envio_arp = async(enviando_arp, capturador, ip_cliente, mac_adaptador, ip_gateway);
//auto recojo_arp = async(recogiendo_arp, capturador, lista_host);

//envio_arp.get();
//recojo_arp.get();
recogiendo_arp(capturador, lista_host);
printf("\nDESPUES: %d\n", lista_host.usuarios.size());
return &lista_host;
}


Compila y funciona, cargan los hosts (pues los muestro en recogiendo_arp() pero al salir me dice que la lista tiene 0 elementos.

Aquí muestro los elementos:

Código (cpp) [Seleccionar]

void recogiendo_arp(pcap_t *capturador, lista_usuarios lista)
{
lista.insertar_host(ip, mac);
//inserto elementos...

printf("   %d up\n", lista.usuarios.size());
for (int i = 0; i < lista.usuarios.size();i++)
{
for (int j = 0; j < 4; j++)
{
printf("%x", lista.usuarios[i].ip[j]);
}
printf("::");
for (int j = 0; j < 6; j++)
{
printf("%x", lista.usuarios[i].mac[j]);
}
printf("\n");
}

// y los muestro me salen que tiene 6, antes de llamar a la funcion tenia 0 claro.


Se me hace raro, el problema está en ese vector dinamico de estructuras y en la asignacion de la memoria, yo simplemente declaro la clase lista_usuarios, y luego la paso a una funcion como parametro para que me cargue elementos en el vector de hosts de esa clase lista_usuarios, lo hace, pero luego desaparecen.  :P :P

Pero al salir, 0 elementos, diría que los elementos nuevos que inserta en el vector están en la memoria de la funcion recogiendo_arp por ello al salir de ella, se pierden.

Si es ese el error.. ¿como corregirlo? Ya he probado a reservar con malloc(sizeof(lista_usuarios)) pero esto no vale para nada, pues lista_usuarios no tiene un tamaño fijo, sino que depende de los elementos que incluya, luego malloc no funcionaría, empiezo a pensar en quitar vector<> y poner un puntero y que vaya modificando el tamaño con realloc(), que sería el camino más dificil, pero una posible solucion, espero no llegar a ella XD


Saludos.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

ivancea96

Código (cpp) [Seleccionar]
recogiendo_arp(capturador, lista_host);

Como dijo Elektro, tienes que pasar la variable por referencia. Así, lo que haces es copiar la variable, y no le haces nada al retornar la función.

Kaxperday

#8
OMG ya esta solucionado.

Mi fallo era que pensaba que al pasar a la funcion la variable su valor se podía modificar, en plan

Código (cpp) [Seleccionar]
void cambia_numero(int num){num=19;}

Eso no debería de funciona, pero si esto que cambiaria el numero:

Código (cpp) [Seleccionar]
void cambia_numero(int *num){*num=19;}

Ok muchas gracias a ambos  ;-) ;-) ;-) ;-) ;-)

De todas formas hay veces que me tiro mucho tiempo para chorradas que ya debería saber hacer XD  :-[

Saludos.
Cuando el poder económico parasita al político ningún partido ni dictador podrá liberarnos de él. Se reserva el 99% ese poder.

ivancea96

CitarDe todas formas hay veces que me tiro mucho tiempo para chorradas que ya debería saber hacer XD

Antes de hacer una función, piensa con mucho cuidado qué va a hacer, qué va a retornar, qué argumentos va a tomar y cómo los va a tomar.