es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

El vector de estructuras que contienen punteros de asignación está fallando al destruirse.

En mi proyecto uso una clase para la asignación de memoria paginada.
Esta clase utiliza una estructura para almacenar todas sus asignaciones:

enum PageStatus: uint_fast8_t { //!< posibles estados de una página asignada
PAGE_STATUS_INVALID = 0b00,
PAGE_STATUS_FREE = 0b01, //!< la página está libre
PAGE_STATUS_USED = 0b10, //!< la página está (parcialmente) usada
};

struct PhysicalPage { //!< representa una página que ha sido asignada
char* pData; //!< puntero a la asignación
PageStatus status; //!< estado de la asignación
};

Estas PhysicalPages se almacenan en un vector std::vector<PhysicalPage> physicalAllocations {};.
Durante la ejecución, se agregan páginas al vector y algunas pueden eliminarse. Durante la eliminación, se elimina el último elemento y se devuelve la memoria utilizando delete page.pData. Sin embargo, surge un problema cuando la clase del asignador alcanza el final de su vida útil y se elimina de la pila. Cuando se llama al destructor del vector de physicalAllocations, intenta destruir no solo los elementos en sí, sino también la memoria reservada (que el vector mantiene como un búfer para cuando se cambia el tamaño). Eso hace que se eliminen punteros de memoria no válidos, lo que detiene la ejecución del programa:

doble liberación o corrupción (!prev)
Señal: SIGABRT (Abortado)

También es probable que valga la pena mencionar que las asignaciones se realizan en bloques más grandes que las páginas, lo que significa que solo uno de cada x punteros son asignaciones válidas. Todos los demás punteros son simplemente desplazamientos de las ubicaciones de memoria reales.

Para evitar que ocurra el error, intenté:

borrado manual (esto es un poco complicado debido a la asignación fragmentada)

for (size_t i = physicalAllocations.size(); 0 < i; i -= 1 << allocationChunkSize) {
delete physicalAllocations[i – (1 << allocationChunkSize)].pData;
for (size_t a = 0; a < 1 << allocationChunkSize; a++)
physicalAllocations.pop_back();
}

borrado del vector

physicalAllocations.clear();

intercambiando por un vector limpio

std::vector<PhysicalPage>(0).swap(physicalAllocations);

de los cuales ninguno funcionó.

He estado trabajando en este problema durante mucho más tiempo del que me gustaría admitir y agradecería mucho su ayuda. ¡Gracias!

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Parece ser que el problema radica en el destructor del vector tratando de borrar el búfer de memoria reservada, lo que causa la eliminación de punteros de memoria no válidos. Una solución para evitar este error es usar un asignador personalizado que no borre el búfer de memoria durante la destrucción del vector.

    Puede definir su clase de asignador personalizado y proporcionarla como segundo parámetro de plantilla al declarar el vector. En la clase de asignador personalizado, puede definir la función de desasignación para no borrar el búfer de memoria reservada.

    Aquí hay una implementación de ejemplo de la clase de asignador personalizado para su caso de uso:

    “`c++
    template
    class CustomAllocator {
    public:
    using value_type = T;

    CustomAllocator() = default;
    
    template <typename u="">
    CustomAllocator(const CustomAllocator<u>&) {}
    
    T* allocate(size_t n) {
        return static_cast<t*>(::operator new(n * sizeof(T)));
    }
    
    void deallocate(T* p, size_t n) {
        // No hacer nada, no borrar el búfer de memoria reservada
    }
    
    template <typename u="">
    bool operator==(const CustomAllocator<u>&) const noexcept {
        return true;
    }
    
    template <typename u="">
    bool operator!=(const CustomAllocator<u>&) const noexcept {
        return false;
    }
    

    };


    Para usar el asignador personalizado con su vector, declárelo de la siguiente manera: ```c++ std::vector<páginafísica,></páginafísica,><páginafísica>> asignacionesFísicas {};

    Usando este método, el búfer de memoria reservado no se borrará durante la destrucción del vector, evitando la eliminación de punteros de memoria no válidos que causaron el error.</páginafísica></t*>

Comments are closed.