elhacker.net cabecera Bienvenido(a), Visitante. Por favor Ingresar o Registrarse
¿Perdiste tu email de activación?.


 


Tema destacado: Píldoras formativas en seguridad de la información


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse)
| | |-+  Duda con punteros y memoria dinamica ...
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Duda con punteros y memoria dinamica ...  (Leído 2,318 veces)
fhaker

Desconectado Desconectado

Mensajes: 15


Ver Perfil
Duda con punteros y memoria dinamica ...
« en: 24 Febrero 2010, 17:16 »

Miren basicamente mi objetivo es lograr almacenar en un array la cantidad de elementos que yo quiera sin haber definido antes esta cantidad ... es decir que la cantidad de elementos de un vector cambie en tiempo de ejecucion ....

se me ocurrio q esto seria posible con punteros y con los comandos new y delete...

he aqui el codigo: (para widnows por el comando system)
Código:
#include <iostream>
#include <string>

using namespace std;

int main()
{
    int *Pa, *aux, i=0;
    string com;
    
    Pa = new int[i+1];
    while(1)
    {
            cout << "Ingrese valor: ";
            getline(cin, com); cout << endl;
            if(com == "end")
                   break;
            Pa[i]=atoi(com.c_str());
            delete[] aux;
            aux = Pa;
            i++;
            cout << "Antes del delete[] Pa: aux[" << i-1 << "] = " << aux[i-1] << endl; //Linea agregada para localizar el error
            delete[] Pa;
            cout << "Luego del delete[] Pa: aux[" << i-1 << "] = " << aux[i-1] << endl; //Linea agregada para localizar el error
            Pa = new int[i+1];
            for(int j=0; j<i; j++)
                     Pa[j] = aux[j];
    }
    cout << "Usted ingreso un vector de " << i << " valores." << endl;
    for(int j=0; j<i; j++)
            cout << Pa[j] << endl;
    delete[] Pa;
    delete[] aux;
    system("pause");
    return 0;
}

el tema es q funciona casi bien jeje ... pq por ejemplo si le meto:
7 1 7 0 "end"
me da todo bien excepto el primer caracter ... y eso me pasa con cualquier cantidad de elementos de valores cualquiera...

es decir siempre me da bien ponga lo q ponga, excepto por el primer elemento el Pa[0] ...

Busque el error y este se da en el momento en q hago un "delete[] Pa" para liberar la memoria antes de redimencionar la matriz para q entre el nuevo elemento ... Y ocurre solo en el primer elemento siempre (el valor erroneo va cambiando, mas abajo hay una foto)


he aqui una foto:


Lo que decia antes .. el valor erroneo q va cambiando a medida que mas dimenciones tiene el vector .. esto es visible en la foto, miren que para la primera dimencion el valor erroneo del primer elemento(el que esta definido luego del "delete[] Pa") es 0 y para la 4ta dimencion (la ultima y la unica que mostraria el programa si no estubiesen las lineas para depurar el programa) es 212960
Si alguien sabe pq pasa esto  se lo agradeceria ...

Fhaker


« Última modificación: 24 Febrero 2010, 17:24 por fhaker » En línea

Eternal Idol
Moderador
***
Desconectado Desconectado

Mensajes: 5.508


La mano invisible del mercado me robo la billetera


Ver Perfil WWW
Re: Duda con punteros y memoria dinamica ...
« Respuesta #1 en: 24 Febrero 2010, 17:32 »

La primera vez cuando haces delete[] aux; aux tiene un valor indefinido, eso esta mal seguro.  Revisa el codigo completo, es muy poco claro ...


En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
fhaker

Desconectado Desconectado

Mensajes: 15


Ver Perfil
Re: Duda con punteros y memoria dinamica ...
« Respuesta #2 en: 24 Febrero 2010, 17:53 »

va de nuevo:

esta vez defini aux antes del while ... y le coloque comentarios para aclarar el code:

Código:
#include <iostream>
#include <string>

using namespace std;

int main()
{
    int *Pa, *aux, i=0;
    string com;
    
    Pa = new int[i+1]; //Declaro una matriz de 1 elemento en la memoria del monton ... esto es asi para que en los respectivos ciclos del bucle de abajo siempre entre un nuevo elemento ...
    aux = new int[i+1]; //Esto me dijo Eternal Idol que lo ponga pero yo tenia entendido que no hacia falta colocarlo ...
    while(1)
    {
            cout << "Ingrese valor: ";
            getline(cin, com); //Tomo lo ingresado por teclado y lo guardo en un objeto de la clase string
            cout << endl;
            if(com == "end") //Verifico que lo ingresado por teclado no sea "end"
                   break;
            Pa[i]=atoi(com.c_str()); //Convierto el string que contiene los datos ingresados por teclado en un int y lo guardo en el elemento i del array ... Esto no seria posible sino hubiese hecho el "Pa = new int[i+1]" antes de entrar al while...
            delete[] aux; //Libero la memoria que ocupa aux ... esto lo hago para que en ciclos suscesivos no quede la memoria sin liberar.
            aux = Pa; //Aca hago que aux apunte a donde apunta Pa ... ahora aux esta en la memoria del monton y debe ser liberada antes de terminar la ejecucion del programa, esto justifica la linea anterior.
            i++; //Aumento el valor de i, preparando todo para q se ingrese el nuevo elemento ... Esto es asi pq com != "end" ... Es decir se dio lugar a la posibilidad de que se ingrese un nuevo elemento en el proximo ciclo ...
            cout << "Antes del delete[] Pa: aux[" << i-1 << "] = " << aux[i-1] << endl; //Linea que no hace efectos al soft, se usa solo para depurar y esta no estaria si el soft funcionace como corresponde ..
            delete[] Pa; //Libero la memoria a la cual apuntaba Pa, pero la informacion no se pierde gracias a que aux esta apuntando ahi todavia
            cout << "Luego del delete[] Pa: aux[" << i-1 << "] = " << aux[i-1] << endl; //Linea que no hace efectos al soft, se usa solo para depurar y esta no estaria si el soft funcionace como corresponde ..
            Pa = new int[i+1]; //Declaro el nuevo array en la memoria del monton esta vez con un elemento mas gracias al i++ hecho antes ...
            for(int j=0; j<i; j++) //En este for le vuelvo a meter a Pa todos los elementos que tenia antes de hacer el "delete[] pa", esos datos siguen siendo accesibles gracias a q aux sigue apuntando a donde estos estan..
                     Pa[j] = aux[j];
    }
    cout << "Usted ingreso un vector de " << i << " valores." << endl;
    for(int j=0; j<i; j++)
            cout << Pa[j] << endl;
    delete[] Pa;
    delete[] aux;
    system("pause");
    return 0;
}

PD: yo le llamo "memoria del monton" a toda la memoria q no estaba reservada pro el soft y q se "toma y libera" en tiempo de ejecucion mediante los comandos new y delete
« Última modificación: 24 Febrero 2010, 18:01 por fhaker » En línea

Eternal Idol
Moderador
***
Desconectado Desconectado

Mensajes: 5.508


La mano invisible del mercado me robo la billetera


Ver Perfil WWW
Re: Duda con punteros y memoria dinamica ...
« Respuesta #3 en: 24 Febrero 2010, 18:00 »

delete[] Pa; //Libero la memoria a la cual apuntaba Pa, pero la informacion no se pierde gracias a que aux esta apuntando ahi todavia

Esto es C++, si pedis liberar la memoria la libera y en aux tenes un puntero a memoria invalida.
En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
fhaker

Desconectado Desconectado

Mensajes: 15


Ver Perfil
Re: Duda con punteros y memoria dinamica ...
« Respuesta #4 en: 24 Febrero 2010, 18:08 »

delete[] Pa; //Libero la memoria a la cual apuntaba Pa, pero la informacion no se pierde gracias a que aux esta apuntando ahi todavia

Esto es C++, si pedis liberar la memoria la libera y en aux tenes un puntero a memoria invalida.


Aaaa muchas gracias, es bueno saberlo jeje ... pasa q esto lo hago como practica para aprender punteros (es decir estoy aprendiendo), y la verdad q no sabia esto...

Y si en vez de hacer delete[] Pa, hiciera un delete[] aux en esa misma linea, tambien seria inaccesible para Pa


es decir:

Código:
Pa = new int[i];
aux = Pa;
delete[] aux;

se q seria estupido hacer eso ya que le damos un valor a un objeto y luego lo borramos, pero tomemoslo a modo de ejemplo ... me quedaria Pa como un puntero a memoria invalida???


En línea

Eternal Idol
Moderador
***
Desconectado Desconectado

Mensajes: 5.508


La mano invisible del mercado me robo la billetera


Ver Perfil WWW
Re: Duda con punteros y memoria dinamica ...
« Respuesta #5 en: 24 Febrero 2010, 18:10 »

De esa manera tendrias dos punteros a memoria invalida (ya liberada): Pa y aux.
En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
fhaker

Desconectado Desconectado

Mensajes: 15


Ver Perfil
Re: Duda con punteros y memoria dinamica ...
« Respuesta #6 en: 24 Febrero 2010, 18:25 »

O sea q lo unico q me queda es definir a aux en memoria independiente de la de Pa y hacer un "backup" de los valores de Pa en cada ciclo del while antes de cada delete[]

q poco practico xD :P

Gracias!
En línea

Eternal Idol
Moderador
***
Desconectado Desconectado

Mensajes: 5.508


La mano invisible del mercado me robo la billetera


Ver Perfil WWW
Re: Duda con punteros y memoria dinamica ...
« Respuesta #7 en: 24 Febrero 2010, 18:26 »

Siempre hay mas de una manera de hacer las cosas, ejemplo:

Código
  1. #include <iostream>
  2. #include <string>
  3.  
  4. using namespace std;
  5.  
  6. bool getNumber(int &num)
  7. {
  8.  string com;
  9.  cout << "Ingrese valor: ";
  10.  getline(cin, com);
  11.  cout << endl;
  12.  if (com == "end")
  13.  {
  14.    return false;
  15.  }
  16.  num = atoi(com.c_str());
  17.  return true;
  18. }
  19.  
  20. int main()
  21. {
  22.  int *numVec = 0;
  23.  int nElem = 0;
  24.  for (int inputNum = 0; getNumber(inputNum); nElem++)
  25.  {
  26.    int *aux = new int[nElem + 1];
  27.    memcpy(aux, numVec, sizeof(int) * nElem); //en la primera pasada numVec es un puntero nulo pero nElem es 0, entonces no tiene nada que copiar
  28.    aux[nElem] = inputNum
  29.    delete[] numVec; //C++ acepta que llames a los operadores delete y delete[] con un puntero nulo, como numVec en la primera pasada
  30.    numVec = aux;
  31.  }
  32.  
  33.  cout << "Usted ingreso un vector de " << nElem << " valores." << endl;
  34.  for(int j = 0; j < nElem; j++)
  35.  {
  36.    cout << numVec[j] << endl;
  37.  }
  38.  
  39.  delete[] numVec;
  40.  system("pause");
  41.  return 0;
  42. }
En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
fhaker

Desconectado Desconectado

Mensajes: 15


Ver Perfil
Re: Duda con punteros y memoria dinamica ...
« Respuesta #8 en: 24 Febrero 2010, 19:30 »

aca esta mi code, ya funciona gracias eternal


Código:
#include <iostream>
#include <string>

using namespace std;

int main()
{
    int *Pa, *aux, i=0;
    string com;
    
    Pa = new int[i+1];
    while(1)
    {
            cout << "Ingrese valor: ";
            getline(cin, com); cout << endl;
            if(com == "end")
                   break;
            Pa[i]=atoi(com.c_str());
            delete[] aux;
            aux = new int[i+1];
            for(int j=0; j<=i; j++)
                    aux[j] = Pa[j];
            i++;
            delete[] Pa;
            Pa = new int[i+1];
            for(int j=0; j<i; j++)
                     Pa[j] = aux[j];
    }
    cout << "Usted ingreso un vector de " << i << " valores." << endl;
    for(int j=0; j<i; j++)
            cout << Pa[j] << endl;
    delete[] Pa;
    delete[] aux;
    system("pause");
    return 0;
}

Otra cosa:

La primera vez cuando haces delete[] aux; aux tiene un valor indefinido, eso esta mal seguro.  Revisa el codigo completo, es muy poco claro ...

Esto que me dijiste me parece q esta mal, pq en este code hago lo mismo y funciona igual ... yo tenia entendido que delete lo podes usar con un puntero sin asignar...


Y por ultimo:
que funcion es esa de memcpy?

de q libreria es?
« Última modificación: 24 Febrero 2010, 19:33 por fhaker » En línea

Eternal Idol
Moderador
***
Desconectado Desconectado

Mensajes: 5.508


La mano invisible del mercado me robo la billetera


Ver Perfil WWW
Re: Duda con punteros y memoria dinamica ...
« Respuesta #9 en: 24 Febrero 2010, 19:40 »

Esto que me dijiste me parece q esta mal, pq en este code hago lo mismo y funciona igual ... yo tenia entendido que delete lo podes usar con un puntero sin asignar...

¿Y como podria funcionar eso? Indefinido significa que podria tener cualquier valor ... el del main por ejemplo. A delete/delete[] los podes usar con un puntero nulo que no es lo mismo que indefinido.

delete[]:
Cita de: cplusplus.com
Parameters
ptr
    Either a null pointer, or a pointer to a memory block to be released, type-casted to a void*.
    This pointer value should have been returned by a previous call to operator new[].

http://www.cplusplus.com/reference/std/new/operator%20delete%5B%5D/

delete:
Cita de: cplusplus.com
Parameters
ptr
    Either a null pointer, or a pointer to a memory block to be released, type-casted to a void*.
    This pointer value should have been returned by a previous call to operator new.
http://www.cplusplus.com/reference/std/new/operator%20delete/

En definitiva funciona de casualidad y podria fallar en cualquier ejecucion  ;D


Y por ultimo:
que funcion es esa de memcpy?

de q libreria es?

Es una funcion standard mas vieja que C++, la podes encontrar en cstring o string.h:
http://www.cplusplus.com/reference/clibrary/cstring/memcpy/
« Última modificación: 24 Febrero 2010, 19:52 por Eternal Idol » En línea

La economía nunca ha sido libre: o la controla el Estado en beneficio del Pueblo o lo hacen los grandes consorcios en perjuicio de éste.
Juan Domingo Perón
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines