2009-11-15 21 views
10

Me pregunto si el C o C++ estándar garantiza que el puntero no se cambia cuando realloc se llama con un (distinto de cero) de menor tamaño:¿puede mover el puntero de realloc si el nuevo tamaño es más pequeño?

size_t n=1000; 
T*ptr=(T*)malloc(n*sizeof(T)); 
//<--do something useful (that won't touch/reallocate ptr of course) 
size_t n2=100;//or any value in [1,n-1] 
T*ptr2=(T*)realloc(ptr,n2*sizeof(T)); 
//<-- are we guaranteed that ptr2==ptr ? 

Básicamente, puede el sistema operativo decidir sobre su propia que desde liberamos un gran bloque de memoria, quiere aprovechar todos los realocos para desfragmentar la memoria, y de alguna manera mover ptr2?

Respuesta

6

Con realloc, no hay absolutamente ninguna garantía sobre dónde va a vivir la memoria después de las palabras. Creo que el malloc predeterminado de libc solo copiará la memoria a regañadientes, por lo que, en términos prácticos, puede estar bien. Pero no cuentes con eso.

16

http://opengroup.org/onlinepubs/007908775/xsh/realloc.html

Al completar con éxito con un tamaño no es igual a 0, realloc() devuelve un puntero al espacio (posiblemente desplazado) asignado.

No, no es garantía

+1

Anteriormente en esa página, dice "La función realloc() cambia el tamaño del objeto de memoria apuntado por ptr al tamaño especificado por tamaño. El contenido del objeto permanecerá sin cambios hasta el menor de los nuevos y tamaños antiguos. Si el nuevo tamaño del objeto de memoria requeriría movimiento del objeto, se libera el espacio para la instanciación previa del objeto ". No descarta el movimiento, pero es relativamente poco probable. –

+1

Sí, aún tiene garantizado que todo lo que había en la memoria todavía estaría allí, gracias por señalar –

0

En Windows, el tiempo de ejecución de C-agarra un montón, y luego asigna memoria de ese montón. Por lo tanto, el sistema operativo no conocerá las asignaciones de memoria individuales, y por lo tanto no moverá las cosas.

+1

Esto no es correcto. Por un lado, el tiempo de ejecución de Visual C no llama directamente a la implementación del montón del sistema operativo. Por otro lado, la llamada HeapReAlloc() _does_ mueve las cosas. –

+1

Necesita verificar dos veces sus documentos. Ver: http://msdn.microsoft.com/en-us/library/csd157zx.aspx El CRT toma un único montón de sistema operativo para su uso interno. Luego subasigna ese montón (lo que significa que no usa las llamadas al montón de Win32 para hacer asignaciones dentro de ese montón) – DougN

6

No hay garantía realloc devolverá la misma ubicación, punto.

+0

Sería bueno si esto se definiera definitivamente en alguna parte. No decir que "X está garantizado que suceda" no es lo mismo que afirmar específicamente que "X no se garantiza que suceda". – RoG

4

realloc no está obligado a dejar el bloque en su sitio incluso si encajaría, y de hecho la aplicación trozo más simple es un ejemplo en el que no podría:

  • malloc: sbrk llaman.
  • realloc: llame al malloc y memcpy.
  • free: no-op.

Esto puede sonar ridículo, pero a veces para los sistemas integrados una implementación como la que acabo de describir es en realidad la óptima.

+0

Otro ejemplo es una implementación donde todas las asignaciones adyacentes son bloques del mismo tamaño para evitar la fragmentación. En ese caso, un bloque de 32 bytes ya no pertenece a la misma ubicación que el antiguo bloque de 4096 bytes. –

+0

Sí. Otro ejemplo más avanzado sería una implementación que examina si el lado izquierdo del bloque a encoger es libre, si se creará un bloque libre significativo en el lado derecho al encogerse, si el tamaño resultante es "suficientemente pequeño" "that' memcpy' no es demasiado caro ... y si se cumplen las condiciones adecuadas, mueve el bloque a una nueva ubicación para evitar la fragmentación. –

2

Me parece que todas las respuestas actuales (en el momento de esta respuesta) no se refieren a ningún documento estándar.

Para C++ me referiré a Working Draft, Standard for Programming Language C++, Document Number: N3337, Date: 2012-01-16, Revises: N3291 que, según https://isocpp.org/std/the-standard, es el documento libre más cercano al documento estándar no oficial C++ 11 estándar; aquí nos encontramos en 06.20.13 C biblioteca:

2 Los contenidos son los mismos que la cabecera de la biblioteca estándar de C, con los siguientes cambios: [en mi opinión los cambios mencionados no son relevantes para la pregunta].

Ahora tenemos que referirnos al estándar C.

De acuerdo con https://stackoverflow.com/a/83763/15485, el documento libre más cercano al documento estándar oficial no oficial C11 es Programming languages — C, N1570 Committee Draft — April 12, 2011 ISO/IEC 9899:201x; aquí nos encontramos en 7.22.3.5 La función realloc:

4 La función realloc devuelve un puntero al nuevo objeto (que pueden tener el mismo valor que un puntero al objeto antiguo), o un puntero nulo si el nuevo objeto no pudo ser asignado.

No soy un hablante nativo de inglés, por lo que es usted quien debe interpretar el significado de "puede tener".

+4

Soy un hablante nativo de inglés (y estoy bastante familiarizado con el estándar C). El texto citado dice que el nuevo puntero puede tener o no el mismo valor que el puntero antiguo, sin que esto implique que esto depende del tamaño. Un motivo (no establecido en el estándar) es que una implementación podría asignar un trozo más pequeño en una ubicación diferente para reducir la fragmentación y hacer que las asignaciones futuras tengan más probabilidades de éxito. Para que haya una garantía de que no se mueve en algunos casos, eso tendría que establecerse explícitamente en la norma. No lo es –

Cuestiones relacionadas