¿Cómo puedo obtener el tamaño de un bloque de memoria asignado usando malloc ()? [duplicar]

StackOverflow https://stackoverflow.com/questions/1208644

Pregunta

  

Posibles duplicados:
   ¿Cómo puedo obtener el tamaño de una matriz desde un puntero en C?
   ¿Existe? ¿Alguna forma de determinar el tamaño de una matriz de C ++ mediante programación? Y si no, ¿por qué?

Obtengo un puntero a una parte de la memoria asignada de una función de estilo C. Ahora, sería realmente interesante para fines de depuración saber cómo grande es el bloque de memoria asignado que señala este puntero.

¿Hay algo más elegante que provocar una excepción al correr a ciegas sobre sus límites?

Gracias de antemano, Andreas

EDITAR:

Uso VC ++ 2005 en Windows y GCC 4.3 en Linux

EDIT2:

Tengo _msize bajo VC ++ 2005 Desafortunadamente, se traduce en una excepción en el modo de depuración ...

EDIT3:

Bueno. He intentado de la manera descrita anteriormente con la excepción, y funciona. Al menos mientras estoy depurando y asegurándome que inmediatamente después de la llamada a las salidas de la biblioteca corro sobre los límites del búfer. Funciona como un encanto.

Simplemente no es elegante y de ninguna manera se puede utilizar en el código de producción.

¿Fue útil?

Solución

No es estándar, pero si su biblioteca tiene una función msize () que le dará el tamaño.

Una solución común es envolver malloc con su propia función que registra cada solicitud junto con el tamaño y el rango de memoria resultante, en la versión de lanzamiento puede volver al "código real" malloc .

Otros consejos

Si no te importa la violencia sorda por depurar, puedes # definir macros para enlazar llamadas a malloc y liberar y rellenar los primeros 4 bytes con el tamaño.

Al ritmo de

void *malloc_hook(size_t size) {
    size += sizeof (size_t);
    void *ptr = malloc(size);
    *(size_t *) ptr = size;
    return ((size_t *) ptr) + 1;
}

void free_hook (void *ptr) {
    ptr = (void *) (((size_t *) ptr) - 1);
    free(ptr);
}

size_t report_size(ptr) {
    return * (((size_t *) ptr) - 1);
}

entonces

#define malloc(x) malloc_hook(x)

y así sucesivamente

La biblioteca de tiempo de ejecución de C no proporciona dicha función. Además, provocar deliberadamente una excepción tampoco te dirá qué tan grande es el bloqueo.

Por lo general, la forma en que este problema se resuelve en C es mantener una variable separada que realiza un seguimiento del tamaño del bloque asignado. Por supuesto, esto es a veces inconveniente, pero generalmente no hay otra forma de saberlo.

Su biblioteca de tiempo de ejecución de C puede proporcionar algunas funciones de depuración del montón que pueden consultar bloques asignados (después de todo, free () necesita saber qué tan grande es el bloque), pero cualquiera de este tipo de cosas no será portátil.

Con gcc y el GNU linker , puede envolver fácilmente malloc

#include <stdlib.h>
#include <stdio.h>


void* __real_malloc(size_t sz);
void* __wrap_malloc(size_t sz)
{
    void *ptr;

    ptr = __real_malloc(sz);
    fprintf(stderr, "malloc of size %d yields pointer %p\n", sz, ptr);

    /* if you wish to save the pointer and the size to a data structure, 
       then remember to add wrap code for calloc, realloc and free */

    return ptr;
}

int main()
{
    char *x;
    x = malloc(103);

    return 0;
}

y compila con

gcc a.c -o a -Wall -Werror -Wl,--wrap=malloc

(Por supuesto, esto también funcionará con el código c ++ compilado con g ++, y con el nuevo operador (a través de su nombre mutilado) si lo desea).

En efecto, la biblioteca cargada estática / dinámicamente también usará su __wrap_malloc .

No, y no puede confiar en una excepción al sobrepasar sus límites, a menos que esté en la documentación de su implementación. Es parte de lo que realmente no necesitas saber para escribir programas. Investigue la documentación o el código fuente de su compilador si realmente quiere saberlo.

No hay una función estándar de C para hacer esto. Dependiendo de su plataforma, puede haber un método no portátil: ¿qué biblioteca OS y C está utilizando?

Tenga en cuenta que provocar una excepción no es confiable: puede haber otras asignaciones inmediatamente después de la porción que tiene, por lo que es posible que no obtenga una excepción hasta mucho después de que exceda los límites de su porción actual.

Comprobadores de memoria como memcheck de Valgrind y TCMalloc de Google (la parte del verificador de pila) realiza un seguimiento de este tipo de cosas.

Puede usar TCMalloc para volcar un perfil de montón que muestra dónde se asignaron las cosas, o simplemente puede hacer que se revise para asegurarse de que su montón sea el mismo en dos puntos en la ejecución del programa usando SameHeap () .

Solución parcial: en Windows puede usar PageHeap para capturar un acceso de memoria fuera del bloque asignado.

PageHeap es un administrador de memoria alternativo presente en el kernel de Windows (en las variedades NT, pero nadie debería usar ninguna otra versión hoy en día). Toma cada asignación en un proceso y devuelve un bloque de memoria que tiene su final alineado con el final de una página de memoria, luego hace que la siguiente página sea inaccesible (sin lectura, sin acceso de escritura). Si el programa intenta leer o escribir más allá del final del bloqueo, obtendrás una infracción de acceso que puedes detectar con tu depurador favorito.

Cómo obtenerlo: descargue e instale el paquete Debugging Tools para Windows de Microsoft: http://www.microsoft.com/whdc/devtools/debugging/default.mspx

luego inicie la utilidad GFlags, vaya a la tercera pestaña e ingrese el nombre de su ejecutable, luego presione la tecla. Marca la casilla de verificación PageHeap, haz clic en Aceptar y listo.

Lo último: cuando haya terminado con la depuración, no olvide volver a ejecutar GFlags y deshabilite PageHeap para la aplicación. GFlags ingresa esta configuración en el Registro (bajo HKLM \ Software \ Microsoft \ Windows NT \ CurrentVersion \ Image File Execution Options \), por lo que es persistente, incluso entre reinicios.

Además, tenga en cuenta que el uso de PageHeap puede aumentar enormemente las necesidades de memoria de su aplicación.

La forma de hacer lo que quiere es SER el asignador. Si filtra todas las solicitudes y luego las graba para fines de depuración, puede averiguar qué desea cuando la memoria está libre.

Además, puede verificar al final del programa para ver si se liberaron todos los bloques asignados y, si no, enumerarlos. Una biblioteca ambiciosa de este tipo podría incluso tomar los parámetros FUNCIÓN y LÍNEA a través de una macro para que sepa exactamente dónde está perdiendo memoria.

Finalmente, MSVCRT de Microsoft proporciona un montón de depuración que tiene muchas herramientas útiles que puede usar en su versión de depuración para encontrar problemas de memoria: http://msdn.microsoft.com/en-us/library/bebs9zyz.aspx

En Linux, puedes usar valgrind para encontrar muchos errores. http://valgrind.org/

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top