2008-11-09 16 views
6

Dado un puntero a alguna variable ... ¿hay alguna manera de comprobar si se asignó estática o dinámicamente?Comprobando si algo fue malloced

+0

Por curiosidad, lo que motiva el deseo de hacer esto? – Dan

+0

estoy haciendo un método que básicamente eliminará una estructura. tiene un miembro de datos que es un puntero a algo que puede estar o no malloced .. dependiendo de cuál, me gustaría liberarlo –

Respuesta

9

Citando de su comentario:

im haciendo un método que básicamente deshacerse de una estructura. que tiene un miembro de datos que es un puntero a algo que puede o no puede ser malloced .. dependiendo de cuál, me gustaría liberarlo

La forma correcta es añadir otra miembro a la estructura : un puntero a una función de desasignación.

No es solo asignación estática versus dinámica. Hay varios posibles asignadores, de los cuales malloc() es solo uno.

En los sistemas Unix, podría ser:

  • una variable estática
  • en la pila
  • en la pila pero asignada dinámicamente (es decir alloca())
  • en el montón, asignaron con malloc()
  • En el montón, asignado con new
  • En el montón, en el medio de una matriz asigna con new[]
  • en el montón, dentro de un struct asignado con malloc()
  • en el montón, dentro de una clase base de un objeto asignado con new
  • Numerado con mmap
  • Numerado con una asignador de encargo
  • hay muchas más opciones, incluyendo varias combinaciones y variaciones de lo anterior

En Windows, también tiene seve ral runtimes, LocalAlloc, GlobalAlloc, HeapAlloc (con varios montones que puede crear fácilmente), y así sucesivamente.

Siempre debe liberar la memoria con la función de liberación correcta para el asignador que utilizó. Entonces, o la parte del programa responsable de asignar la memoria también debe liberar la memoria, o debe pasar la función de liberación correcta (o un envoltorio alrededor) al código que liberará la memoria.

También puede evitar todo el problema requiriendo que el puntero siempre se asigne con un asignador específico o proporcionando el asignador usted mismo (en la forma de una función para asignar la memoria y posiblemente una función para liberarla). Si proporciona el asignador usted mismo, incluso puede utilizar trucos (como punteros etiquetados) para permitir que uno también utilice la asignación estática (pero no entraré en los detalles de este enfoque aquí).

Raymond Chen tiene un blog sobre ello (Windows-céntrico, pero los conceptos son los mismos en todas partes): Allocating and freeing memory across module boundaries

0

¿Se puede enganchar en malloc() como los depuradores malloc, usando LD_PRELOAD o algo así? De ser así, podría mantener una tabla de todos los punteros asignados y usar eso. De lo contrario, no estoy seguro. ¿Hay alguna forma de acceder a la información contable de malloc?

2

La biblioteca ACE hace esto por todos lados. Es posible que pueda verificar cómo lo hacen. En general, probablemente no necesite hacer esto en primer lugar ...

0

No es una función estándar.
Una versión de depuración de su biblioteca malloc puede tener alguna función para hacer esto.

0

Puede comparar su dirección con algo que sabe que es estático, y decir que está malloced solo si está lejos, si conoce el alcance del que debería proceder, pero si su alcance es desconocido, no puede realmente confía en eso.

2

Dado que el montón, la pila y el área de datos estáticos generalmente ocupan diferentes rangos de memoria, es posible conocer el mapa de la memoria del proceso, conocer la dirección y determinar en qué área de asignación se encuentra. La técnica es tanto específica de la arquitectura como del compilador, por lo que hace que portar el código sea más difícil.

2

La mayoría de las implementaciones de libc malloc funcionan almacenando un encabezado antes de cada bloque de memoria devuelto que tiene campos (para ser utilizados por la llamada libre) que tiene información sobre el tamaño del bloque, así como un valor 'mágico' . Este valor mágico es para proteger contra el usuario al eliminar accidentalmente un puntero que no fue asignado (o liberar un bloque que fue sobrescrito por el usuario). Es muy específico del sistema, por lo que tendrías que mirar la implementación de tu biblioteca libc para ver exactamente qué valor mágico había allí.

Una vez que lo sepa, mueva el puntero dado hacia atrás para apuntar al encabezado y luego verifique el valor mágico.

0

1.) Obtenga un archivo de mapa para el código que tiene.

2.) La plataforma de destino del proceso/hardware subyacente debe tener un archivo de mapa de memoria que normalmente indique la dirección de inicio de la memoria (pila, montón, global0, tamaño de ese bloque, atributos de lectura-escritura de ese bloque de memoria)

3.) Después de obtener la dirección del objeto (variable del puntero) desde el archivo mao en 1.) intente ver en qué bloque cae esa dirección. puede tener una idea.

= AD