Pregunta

Dado un puntero a alguna variable ... ¿hay alguna forma de verificar si se asignó estática o dinámicamente?

¿Fue útil?

Solución

Citando su comentario:

  

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 mal colocado o no ... dependiendo de cuál, me gustaría liberarlo

La forma correcta es agregar otro miembro a la estructura: un puntero a una función de desasignación.

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

En sistemas tipo 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, asignado con malloc()
  • En el montón, asignado con new
  • En el montón, en el medio de una matriz asignada con new[[
  • En el montón, dentro de una estructura asignada con malloc()
  • En el montón, dentro de una clase base de un objeto asignado con new
  • Asignado con mmap
  • Asignado con un asignador personalizado
  • Muchas más opciones, incluidas varias combinaciones y variaciones de las anteriores

En Windows, también tiene varios tiempos de ejecución, LocalAlloc , GlobalAlloc , HeapAlloc (con varios montones que puede crear fácilmente) y etc.

Siempre debe liberar 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 una envoltura a su alrededor) al código que liberará la memoria.

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

Raymond Chen tiene una publicación de blog al respecto (centrada en Windows, pero los conceptos son lo mismo en todas partes): Asignación y liberación de memoria a través de los límites del módulo

Otros consejos

La ACE hace esto en todo el lugar. Es posible que pueda verificar cómo lo hacen. En general, probablemente no debería necesitar hacer esto en primer lugar, sin embargo ...

Dado que el montón, la pila y el área de datos estáticos generalmente ocupan diferentes rangos de memoria, es posible, con un conocimiento profundo del mapa de memoria del proceso, observar la dirección y determinar en qué área de asignación se encuentra. Esta técnica es a la vez arquitectura y compilador específicos, por lo que dificulta la transferencia de su código.

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 free ()) 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ía que mirar la implementación de su biblioteca libc para ver exactamente qué valor mágico había allí.

Una vez que sabe eso, mueve el puntero dado hacia atrás para apuntar al encabezado y luego verifica el valor mágico.

¿Se puede conectar a malloc (), como hacen los depuradores de malloc, usando LD_PRELOAD o algo así? Si es así, puede mantener una tabla de todos los punteros asignados y usarla. De lo contrario, no estoy seguro. ¿Hay alguna manera de obtener información sobre la contabilidad de malloc?

No como una característica estándar.
Una versión de depuración de su biblioteca malloc podría tener alguna función para hacer esto.

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

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

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

3.) Después de obtener la dirección del objeto (variable de puntero) del archivo mao en 1.) intente ver en qué bloque cae esa dirección. podrías tener alguna idea.

= AD

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