2009-08-20 6 views
5

Digamos que tengo un puntero asignado para contener 4096 bytes. ¿Cómo se podrían desasignar los últimos 1024 bytes en C? ¿Qué tal en C++? ¿Qué pasaría si, en cambio, quisiera desasignar el primero 1024 bytes y mantener el resto (en ambos idiomas)? ¿Qué hay de la desasignación desde la mitad (me parece que esto requeriría dividirlo en dos punteros, antes y después de la región desasignada).C y C++: Liberación PARTE de un puntero asignado

+0

no estoy seguro, pero usar el puntero "falso" con el tamaño correcto, eliminar o liberar el que desea debería hacer el truco, necesita al menos 2 punteros. – claf

+1

@claferri. Eso es un comportamiento indefinido. Solo puede liberar punteros() devueltos desde malloc/realloc; de lo contrario, ¿cómo sabe free() cuánto liberar? – Roddy

+0

@roddy: oups tienes razón :) – claf

Respuesta

2

Si tiene n bytes de memoria malloc ado, puede reallocm bytes (donde m < n) y por lo tanto tirar a la basura los últimos n-m bytes.

Para tirar desde el principio, puede malloc un nuevo y más pequeño búfer y memcpy los bytes que desea y luego free el original.

La última opción también está disponible con C++ new y delete. También puede emular el primer caso realloc.

+1

"malloc/memcpy/free" es cómo se puede implementar realloc internamente. – Roddy

+1

Acepto que realloc generalmente devolverá la (misma) primera parte, pero ¿es un requisito oficial para realloc? Creo que aquí podría haber implementaciones que podrían mover los datos a un nuevo lugar. –

+0

Imagine un esquema de reasignación inteligente en el que se rastrea el patrón histórico de asignaciones ... si ha habido solicitudes de asignación recientes para 4096 bytes, podría ser mejor mover el bloque de contracción en otro lugar para liberar este bloque 4K. En ese caso, la dirección cambiará. Y realloc devuelve un puntero a la nueva área de memoria, por lo que el programador debería usarla. Si cambia o no. – xcramps

1

Puede acortarlo con realloc(). No creo que el resto sea posible.

1

Puede usar realloc() para hacer que la memoria sea más corta. Tenga en cuenta que para algunas implementaciones, tal llamada no hará nada. No puede liberar el primer bit del bloque y retener el último bit.

Si necesita este tipo de funcionalidad, debería considerar el uso de una estructura de datos más compleja. Una matriz no es la respuesta correcta a cada problema de programación.

+0

Estoy implementando un sistema de memoria, así que estoy buscando obtener como bajo nivel de acceso como puedo mientras permanezco portátil. – Imagist

1

http://en.wikipedia.org/wiki/New_(C%2B%2B)

Resumen: En contraste con realloc de C, que no es posible reasignar directamente memoria asignada con el nuevo []. Para ampliar o reducir el tamaño de un bloque, uno debe asignar un nuevo bloque de tamaño adecuado , copiar sobre la memoria anterior y eliminar el bloque anterior. La biblioteca estándar de C++ proporciona una matriz dinámica que se puede ampliar o reducir en su plantilla std :: vector.

12

No intente y adivine la administración de la memoria. Por lo general es más inteligente de lo que ;-)

El único que se puede alcanzar es el primer escenario a 'deallocate' el último 1K

char * foo = malloc(4096); 

foo = realloc(foo, 4096-1024); 

Sin embargo, incluso en este caso, no hay garantía de que "foo "no se modificará". Puede liberar su 4K completo y realloc() puede mover su memoria a otra parte, invalidando así cualquier apuntador que pueda tener.

Esto es válido tanto para C y C++ - Sin embargo, el uso de malloc() en C++ es un mal olor de código, y la mayoría de la gente esperaría que utilice nueva() a asignar almacenamiento. Y la memoria asignada con new() no puede ser realloc() ed, o al menos, no de ninguna manera portátil.Los vectores STL serían un enfoque mucho mejor en C++

5

No tiene "un puntero asignado para contener 4096 bytes", tiene un puntero a un bloque asignado de 4096 bytes.

Si su bloque fue asignado con malloc(), realloc() le permitirá reducir o aumentar el tamaño del bloque. Sin embargo, la dirección de inicio del bloque no necesariamente será la misma.

No puede cambiar la dirección de inicio de un bloque de memoria malloc 'd, que es realmente lo que su segundo escenario está haciendo. Tampoco hay forma de dividir un bloque malloc 'd.

Ésta es una limitación de la malloc/calloc/realloc/free API - e implementaciones pueden depender de estas limitaciones (por ejemplo, mantener la información de contabilidad sobre la asignación inmediatamente antes de la dirección de inicio, lo que haría mover la dirección de inicio difícil)

Ahora, malloc no es el único asignador por ahí -. su plataforma o bibliotecas podrían proporcionar otros, o se puede escribir su propia (que se hace memoria del sistema a través malloc, mmap, o algún VirtualAlloc otro mecanismo) y luego lo distribuye a su programa de la manera que desee.

Para C++, si asigna memoria con std::malloc, se aplica la información anterior. Si está utilizando new y delete, está asignando almacenamiento y construyendo objetos, por lo que cambiar el tamaño de un bloque asignado no tiene sentido: los objetos en C++ tienen un tamaño fijo.

Cuestiones relacionadas