13.01.2015 Views

Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO

Pensar en C++ (Volumen 1) - Grupo ARCO

SHOW MORE
SHOW LESS

Create successful ePaper yourself

Turn your PDF publications into a flip-book with our unique Google optimized e-Paper software.

✐<br />

✐<br />

✐<br />

“Volum<strong>en</strong>1” — 2012/1/12 — 13:52 — page 382 — #420<br />

✐<br />

Capítulo 13. Creación dinámica de objetos<br />

malloc() con calloc() o realloc()).<br />

Se invoca malloc(), que pide un bloque de memoria. (Este código realm<strong>en</strong>te<br />

puede ser parte de malloc()).<br />

Ahora ti<strong>en</strong>e lugar la búsqueda de un bloque de tamaño adecuado de <strong>en</strong>tre los<br />

bloques libres. Esto requiere la comprobación de un mapa o directorio de algún tipo<br />

que lleve el registro de los bloques disponibles y de los que están <strong>en</strong> uso. Es un<br />

proceso rápido, pero puede que necesite varias pruebas, es pues un proceso no determinista.<br />

Dicho de otro modo, no se puede contar con que malloc() tarde siempre<br />

exactam<strong>en</strong>te el mismo tiempo <strong>en</strong> cada búsqueda.<br />

Antes de <strong>en</strong>tregar el puntero del bloque obt<strong>en</strong>ido, hay que registrar <strong>en</strong> alguna<br />

parte su tamaño y localización para que malloc() no lo vuelva a usar y para que<br />

cuando se produzca la llamada a free(), el sistema sepa cuánto espacio ha de liberar.<br />

El modo <strong>en</strong> que se implem<strong>en</strong>tan todas estas operaciones puede variar mucho.<br />

No hay nada que impida que puedan implem<strong>en</strong>tarse las primitivas de asignación<br />

de memoria <strong>en</strong> el conjunto de instrucciones del procesador. Si es sufici<strong>en</strong>tem<strong>en</strong>te curioso,<br />

pued<strong>en</strong> escribir programas que permitan averiguar cómo está implem<strong>en</strong>tada<br />

malloc(). Si dispone de él, puede leer el código fu<strong>en</strong>te de la biblioteca de funciones<br />

de C, si no, siempre está disponible el de GNU C.<br />

13.2. Rediseño de los ejemplos anteriores<br />

Puede reescribirse el ejemplo Stash que vimos anteriorm<strong>en</strong>te <strong>en</strong> el libro, haci<strong>en</strong>do<br />

uso de los operadores new y delete, con las características que se han visto<br />

desde <strong>en</strong>tonces. A la vista del nuevo código se pued<strong>en</strong> repasar estas cuestiones.<br />

Hasta este punto del libro, ninguna de las clases Stash ni Stack poseerán los<br />

objetos a los que apuntan; es decir, cuando el objeto Stash o Stack sale de ámbito,<br />

no se invoca delete para cada uno de los objetos a los que apunta. La razón por la<br />

que eso no es posible es porque, <strong>en</strong> un int<strong>en</strong>to de conseguir más g<strong>en</strong>eralidad, utilizan<br />

punteros void. Usar delete con punteros void libera el bloque de memoria pero,<br />

al no existir información de tipo, el compilador no sabe qué destructor debe invocar.<br />

13.2.1. delete void* probablem<strong>en</strong>te es un error<br />

Es necesario puntualizar que, llamar a delete con un argum<strong>en</strong>to void* es casi<br />

con seguridad un error <strong>en</strong> el programa, a no ser que el puntero apunte a un objeto<br />

muy simple; <strong>en</strong> particular, que no t<strong>en</strong>ga un destructor. He aquí un ejemplo ilustrativo:<br />

//: C13:BadVoidPointerDeletion.cpp<br />

// Deleting void pointers can cause memory leaks<br />

#include <br />

using namespace std;<br />

class Object {<br />

void* data; // Some storage<br />

const int size;<br />

const char id;<br />

public:<br />

Object(int sz, char c) : size(sz), id(c) {<br />

382<br />

✐<br />

✐<br />

✐<br />

Hooray! Your file is uploaded and ready to be published.

Saved successfully!

Ooh no, something went wrong!