Las 20 líneas de la vergüenza

05 de abril 2009 · Escrito en C / C + + , Opinión

Mientras que el arroz se cocina, me acordé de un caso curioso que me pasó a mí al principio de su carrera, con la participación de gestión de memoria en C + +. En ese momento yo era mucho más. Novato más joven, más rápido, más arrogante y más ...

A más experimentado compañero de trabajo le estaba explicando a un colega con menos experiencia que por cada nuevo debe haber una eliminación correspondiente. De lo contrario el objeto se mantendrá en la memoria y puede haber pérdidas de memoria.

En este punto, lo interrumpió y le dijo: "No necesariamente, ya que es suficiente que el objeto fuera del alcance por lo que el destructor se llama automáticamente .."

Desde entonces, rodó un debate de 10 minutos con los argumentos y contra argumentos, y todo el equipo viendo todavía. Al final, la mitad del equipo de acuerdo con él y la otra mitad de mí, y en ese momento nadie tenía en mente una forma de comprobar. Busque en la Internet no era una opción.

Como yo tenía todas las respuestas, después de todo ya está programado en PHP, Java y C + + fue de demostrar más adelante que yo tenía razón.

Días más tarde, uno de esos momentos filosófica, me acordé de que una dirección de memoria es un número, y usted puede convertir una dirección a un número común, y van por otro camino, aunque este último suele ser inútil.

Entonces idearon una manera de demostrar mi teoría: se crea un objeto en un ámbito restringido a la asignación de nuevo. Guardar la dirección de este objeto como un número común en un cabo largo de la limitación de la posibilidad, esperamos finalizar el alcance restringido, el destructor de obejto ser llamado y después el ámbito exterior, utilice el número que representa la dirección del objeto para acceder a esa área de memoria mostrando que reciben un SIGSEGV (fallo de segmentación) al tratar de acceder a un área de memoria no válida. Entonces me genera el código de abajo.

  A
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
  # Include
 # Include <string>

 using namespace std;

 int argc, char ** argv ) { int main (int argc, char ** argv) {
     0 ; unsigned long a = 0;

     {
         new string ( "Hello World!!!" ) ; * Str = new String ("Hola Mundo!");
         unsigned long ) str ; a = (unsigned long) calle;

         "str: " << str << endl ; cout <<"str:" <<str <<endl;
         "num: " << num << endl ; cout <<"num:" <<a <<endl;
     }

     * ( ( string * ) num ) << endl ; cout <<* ((* ​​cadena) a) <<endl;

     ; return 0;
 } 

He aquí, para mi sorpresa, el programa no llegó a explotar en la cara. Trabajó correctamente señalando que, de hecho, yo era el que estaba equivocado.

Buscar más me di cuenta de que sí, que debe ser nueva para cada uno y eliminar sólo, y más por cada nuevo [] debe ser uno y sólo un delete []. Lo que yo creía que sabía acerca de la gestión de memoria y el alcance, que probablemente era cierta confusión entre los diferentes idiomas.

Cuando empecé el día de debate antes, cometido todos los errores básicos que un novato se compromete:

  1. Inmiscuirse en el que fue llamado.
  2. Toma de posesión de pie por lo que es correcto sin pruebas.
  3. Subestiman el conocimiento de alguien con más experiencia.
  4. ¿Crees que tienes todas las respuestas sólo porque acaba de ver en clase.
  5. Y pensar que sólo porque conoce los aspectos básicos de varios idiomas, entonces usted tiene todas las respuestas.

Como cualquier buen miembro de la especie Homo sapiens , habló mierda. Mi reacción a este descubrimiento iba a tener todo el equipo y me equivoqué, perdón por decir cosas sin sentido y mostrar las veinte líneas de código que se usa para demostrar esto. Por otra parte, me mostró todas las fuentes que he revisado, e incluso llevó a cabo otros detalles sobre la gestión de memoria que se nos escapa, al igual que las referencias circulares . Esto llevó a un re-diseño de algunas partes del proyecto.

Mis 20 líneas cógigo se conocía como "El 20 líneas de la vergüenza" y natual, así que estaba jodido. Cada vez que alguien tenía alguna duda habló "hay 20 líneas de vegonha para la prueba." El significado era algo así como "no existe una prueba sencilla para que no se avergüence más tarde."

Lo más importante es que mi post-mierda actitud fue bien recibido y traído beneficios para el equipo. Si yo hubiera evitado, tarde o temprano alguien probar que estaba equivocado en frente de todos, o peor aún, detrás de las escenas. Admitir los errores y aprender de ello mostró que estaba dispuesto a ser cuestionado. Además de este equipo demostró que más me pareció arrogante (me parezco más que yo ...), yo sabía que era un ser humano ordinario que han cometido errores como todos los demás, no creo que más que nadie. Esto allanó el camino para que otros miembros del equipo se sienten libres de hacer lo mismo y nos convertimos en un equipo más cohesionado.

Comentarios

  • Marco Antonio

    Muy interesante historia!
    Más de equipaje para los que siguieron el debate!

    Otra cosa interesante es la falta de 18 días para la nueva versión de Ubuntu!
    (Pero es hora ?????????? moscas!)

  • http://blabos.org blab

    Últimamente para mí no time're volar, teletransportarse Goin ...

  • Junio

    Blaber, gracias por pasar la experiencia. Muy rico en texto. Paz y salud para usted.

  • ♣ ♦ ♥ ♠ Hime Cheshire

    Hmm ... no estoy seguro de qué compilador que utilice o la versión de la lengua, pero yo sé, C no muestra errores al acceder a la memoria desasignado menos que esté protegido por el sistema operativo ... El C + + muestra?

  • Blaber http://blabos.org de la ampolla

    En primer lugar, gracias por tu visita!

    Se trata de C + + con g + +, pequeña padawan :)

    Depende de lo que consideran "errores de visualización".

    En tiempo de compilación o en tiempo de ejecución?

    En el caso anterior, la inexperiencia esperada (cacofónico esto!) Alcance la destrucción de salida automática (que no existe un objeto dinámicamente en C + +), seguido por derreferenciação un apuntador que apunta a una zona (antes) de memoria desasignado , provocando un error fatal en tiempo de ejecución.

    Añadir un delete str; después de la línea 14 te darás cuenta de la sutil diferencia.

    Ambas pruebas no dan ninguna advertencia en tiempo de compilación.

  • ♣ ♦ ♥ ♠ Hime Cheshire

    No, no, hablo en el tiempo de ejecución de lo mismo ... Al principio, cuando yo estaba aprendiendo a programar, nuestro maestro nos enseñó antes de vectores ALLOC, malloc y calloc, y por lo tanto, hemos utilizado vectores libremente, sin la asignación de memoria ...

    Rara vez se dio un error de la memoria-protegidos del sistema operativo ...
    Por otra parte, cualquier error no aparece, o la elaboración o ejecución.

    Por supuesto que no fue con los objetos, sólo con C, en las clases de la programación estructurada ... Así que mi pregunta ... En C + +, utilizando nuevas en lugar de Alloc, el programa genera errores en tiempo de ejecución si intenta utilizar una memoria no asignados?

    Creo que sería bueno para ver las especificaciones de la lengua, después de todo, el destructor, y liberar la memoria, usted puede proteger hasta la finalización del programa o algo ... o que no ocurra?

  • Blaber http://blabos.org de la ampolla

    El término "vector que utiliza libremente sin la asignación de memoria", es engañoso, para matrices de memoria es necesario que existan. Probablemente quiere decir "hemos utilizado libremente sin vectores asignar dinámicamente la memoria."

    La especificación dice derreferenciar se produce un puntero nulo en el comportamiento indefinido, que en la mayoría de los sistemas (pero no todos), un error fatal.

    Esto no es lo que se muestra arriba. En el ejemplo no es un intento de acceder a un área "supuestamente" desasignado.

    Puntero nulo! Puntero = a área de memoria no válida.


    int* ptr_null = 0;

    / / Es un puntero nulo ptr_null

    ptr_foo = new int * int (123456);
    eliminar ptr_foo;

    / / Ptr_foo apunta a un área de memoria
    / / Que ya no pertenece a este programa

    printf ("% pn", ptr_null);
    printf ("% pn", ptr_foo);

    Compilar y ejecutar los ejemplos que usted verá la diferencia.

    En cuanto al último párrafo, no, eso no es lo que sucede. Estás mezclando las cosas, el destructor es una rutina que se llama automáticamente cuando un objeto se cancela la asignación, ya sea mediante una llamada a delete objetos asignados dinámicamente en la producción o el alcance de los objetos asignados en el montón.

Sitio en Disqus