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

 

 


Tema destacado: Trabajando con las ramas de git (tercera parte)


+  Foro de elhacker.net
|-+  Programación
| |-+  Programación C/C++ (Moderadores: Eternal Idol, Littlehorse, K-YreX)
| | |-+  Sobrecarga operador+ y miembro puntero...
0 Usuarios y 1 Visitante están viendo este tema.
Páginas: [1] Ir Abajo Respuesta Imprimir
Autor Tema: Sobrecarga operador+ y miembro puntero...  (Leído 2,027 veces)
digimikeh

Desconectado Desconectado

Mensajes: 191


Ver Perfil
Sobrecarga operador+ y miembro puntero...
« en: 18 Junio 2019, 22:11 pm »

Hola nuevamente:

El siguiente código:

Código
  1. #include <iostream>
  2.  
  3. using namespace std;
  4.  
  5. struct s{
  6.  
  7. private:
  8.    double * d = nullptr;      
  9.  
  10. public:
  11.    s() : d{new double}{}
  12.    ~s(){ if (d != nullptr) delete d; }
  13.    void setd(const double _d){ *this->d = _d; }
  14.    double getd() const { return *this->d; }
  15.  
  16. };
  17.  
  18. s operator+(const s & _s0, const s & _s1){
  19.    s ns;
  20.    ns.setd(_s0.getd() + _s1.getd());
  21.    return ns;
  22. }
  23.  
  24. int main(){
  25.  
  26.    s s0;
  27.    s s1;
  28.  
  29.    s s2;
  30.    s2 = s0 + s1;
  31.  
  32.    return 0;
  33. }
  34.  
  35.  

Aqui listo para ejecutar:
https://onlinegdb.com/rJNPQ68kr

Al ejecutar, obtengo el mensaje de error:

*** Error in `./a.out': double free or corruption (fasttop): 0x0000000000795c80 ***                                             
Aborted (core dumped)


Estoy seguro que el problema esta entre el puntero privado y el delete en el destructor, ya que si no uso puntero, compila bien.

Sin embargo, he puesto puntero porque quiero entender qué está pasando.  Me da la impresión de que en la definición del operador+ como se crea el objeto ns al terminar el ámbito, se está destruyendo y esta eliminando el puntero.  Lo cual parece valido, pero no tendría por qué corromper la ejecución, se supone que estoy destruyendo un objeto de copia, no los operandos utilizados.



En línea

Dungeons & dragons;
dragons.Attack();
RayR

Desconectado Desconectado

Mensajes: 243


Ver Perfil
Re: Sobrecarga operador+ y miembro puntero...
« Respuesta #1 en: 18 Junio 2019, 23:29 pm »

Lo que sucede es que cuando se llega aquí:

Código
  1.    s2 = s0 + s1;

el objeto temporal creado por el operador sobrecargado (ns) es asignado a s2. Esto hace que se ejecute el operador de asignación (operator=) para struct s. Dado que tú no programaste ninguno, se usa el generado por el compilador. Éste simplemente copia los valores de las variables miembro, es decir, que luego de la copia, s2.d apunta a la misma dirección que ns.d. Esa memoria se libera cuando ns es destruida. Y luego, cuando s2 es destruida, naturalmente, se vuelve a intentar liberar la misma dirección, lo cual es incorrecto. Que se trate de copias es irrelevante. Lo que importa es que apuntan a la misma dirección, y es un error intentar liberar memoria ya liberada. Pero eso ni siquiera es lo peor. Como te mencioné, en la línea 30, s2.d apuntará a la dirección de ns.d, pero antes de esa línea apuntaba a otra dirección distinta, la cual jamás fue liberada, por lo que tienes una "fuga de memoria" o memory leak.

La solución es sobrecargar también operator=, y en él no copiar los punteros, sino los valores de las direcciones a las que apuntan (reservando y liberando memoria, según sea necesario). Imagino que aún no habrás visto ese tema, pero ya llegarás y verás cómo implementarlo. En general, siempre que tengamos punteros habría que sobrecargar el operador de asignación y proporcionar un constructor de copia.


« Última modificación: 18 Junio 2019, 23:32 pm por RayR » En línea

digimikeh

Desconectado Desconectado

Mensajes: 191


Ver Perfil
Re: Sobrecarga operador+ y miembro puntero...
« Respuesta #2 en: 19 Junio 2019, 00:48 am »

Tienes razón!... me había preocupado de sobrecargar el operador + y no pensé en las consecuencias, debí haber cargado ademas el operador = y después << para imprimirlo...

La lección que me dio esto es que debo pensar en cada sobrecarga de operador necesaria pues una lleva a la otra...

Gracias
En línea

Dungeons & dragons;
dragons.Attack();
Loretz

Desconectado Desconectado

Mensajes: 117


Ver Perfil
Re: Sobrecarga operador+ y miembro puntero...
« Respuesta #3 en: 19 Junio 2019, 02:21 am »


El que se mete con uno se está metiendo con todos...

https://en.cppreference.com/w/cpp/language/rule_of_three

Además:
Un comentario y un error:

El comentario es que cuando dices:
Código:
double getd() const { return *this->d; }
no necesitas aclarar que se trata del miembro 'd' de 'this', de eso no hay dudas. El puntero this se usa en las expresiones cuando es *realmente* necesario, por ejemplo, para salvar alguna ambigüedad (necesario), o porque los nombres de los miembros y parámetros ya han hecho un lío tal que no se sabe quién es quién (un parche que suele usarse para dejar en claro situaciones como "el lío este yo no lo hice así que ahora aguantarse el this").

Y el error:
getd() devuelve *d, y el problema aquí es que *d no fue inicializado, no se le asignó un valor; y pretender acceder en modo lectura (cuando haces s2 = s0 + s1;) a una variable sin inicializar es lo que el estándar define como "Undefined Behavior", que significa que puede suceder cualquier cosa (normalmente mala).



En línea

@XSStringManolo
Hacker/Programador
Colaborador
***
Desconectado Desconectado

Mensajes: 2.399


Turn off the red ligth


Ver Perfil WWW
Re: Sobrecarga operador+ y miembro puntero...
« Respuesta #4 en: 19 Junio 2019, 04:26 am »

Al hacer s2 = s0 + s1 que se supone que hace? Suma s0 d + s1 d ?
En línea

Mi perfil de patrocinadores de GitHub está activo! Puedes patrocinarme para apoyar mi trabajo de código abierto 💖

digimikeh

Desconectado Desconectado

Mensajes: 191


Ver Perfil
Re: Sobrecarga operador+ y miembro puntero...
« Respuesta #5 en: 19 Junio 2019, 05:22 am »

@#Loretz.. efectivamente, olvide darle un valor por default en el constructor.
Respecto al puntero this, pues si, es que el código es borrador, lo hago nada mas que para fines de practica... en un reléase, el this lo utilizo siempre y cuanod tenga dos o mas variables que tengan el mismo nombre..

Aproposito, muchas gracias por compartir lo de la regla de 3...
creo que defintivamente tengo que echarle una repasadita al constructor de copia ademas..


#@String Manolo, pues si, solo que como el puntero d es privado, estoy accediendo con el getter..

En línea

Dungeons & dragons;
dragons.Attack();
Páginas: [1] Ir Arriba Respuesta Imprimir 

Ir a:  

Mensajes similares
Asunto Iniciado por Respuestas Vistas Último mensaje
Duda con sobrecarga de operador ( )
Programación C/C++
Akai 6 4,620 Último mensaje 16 Noviembre 2010, 14:53 pm
por Akai
sobrecarga de operador<<
Programación C/C++
adam96 5 4,533 Último mensaje 17 Diciembre 2010, 19:10 pm
por Littlehorse
Sobrecarga operador +
Programación C/C++
_Enko 4 2,616 Último mensaje 6 Febrero 2015, 14:56 pm
por _Enko
Sobrecarga operador -> [C++]
Programación C/C++
K-YreX 2 1,744 Último mensaje 6 Enero 2019, 17:21 pm
por K-YreX
Sobrecarga de operador « 1 2 »
Programación C/C++
digimikeh 10 5,418 Último mensaje 18 Mayo 2019, 03:39 am
por RayR
WAP2 - Aviso Legal - Powered by SMF 1.1.21 | SMF © 2006-2008, Simple Machines