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.

Boost Interprocess no desea eliminar el objeto de memoria compartida antes de la inicialización.

Tengo esta clase base para usar memoria compartida. Los ejemplos de Boost usan una estructura de eliminación como la siguiente para manejar la memoria compartida. Lo he adaptado para mi clase SharedMemBase.

cpp
//Elimina la memoria compartida en la construcción y destrucción
struct shm_remove
{
shm_remove() { shared_memory_object::remove("MySharedMemory"); }
~shm_remove(){ shared_memory_object::remove("MySharedMemory"); }
} remover;

No quiero eliminar el objeto de memoria compartida en la construcción. En caso de que otro proceso lo esté usando, quiero dejarlo así.

Ahora, si dejo solo el destructor y ocurre cualquier excepción no controlada en el programa principal, entonces el destructor no se llamará y, por lo tanto, mi objeto de memoria compartida no se eliminará.

La próxima vez que trate de crear el objeto, la creación no será exitosa ya que el objeto de memoria compartida existe.

Lo que quiero lograr con esto es tener un único objeto de memoria compartida con el nombre de entrada. Si algún otro proceso intenta bip :: create_only con el mismo nombre, debe fallar, lo que se puede hacer con mi código a continuación. El problema surge cuando ocurren excepciones no controladas: el destructor no se llama, dejando el archivo en la memoria compartida, lo que impide crear una instancia de mi clase

namespace bip = boost::interprocess;

class SharedMemBase
{
protected:
    bip::shared<em>memory</em>object shm<em>;
    const std::string name</em>;

<pre><code>bip::shared_memory_object createShm(const std::string &amp;name)
{
    try
    {
        //esto es lo que tiene boost en los ejemplos
        // no quiero eliminar el objeto compartido si otro proceso
        // lo está usando.
        // bip :: shared_memory_object :: remove (name.c_str ());
        return bip :: shared_memory_object (
            bip::create_only, name.c_str (), bip::read_write);
    }
    catch (const bip::interprocess_exception &amp;e)
    {
        std::cerr &lt;&lt; &quot; El objeto de memoria compartida existe con nombre: &quot;
                  &lt;&lt; name &lt;&lt; std::endl;
        throw e;
    }
}
</code></pre>

public:
    SharedMemBase(const std::string &name)
        : name<em>(name),
          shm</em>(createShm(name)) {}

<pre><code>~SharedMemBase()
{
    //esto esta bien
    bip::shared_memory_object::remove(name_.c_str());
}
</code></pre>

};

int main()
{
    SharedMemBase shm_obj("nombre");

<pre><code>throw std::runtime_error(&quot; Alguna excepción aleatoria no controlada &quot;);

return 0;
</code></pre>

}
Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Pregunta

    ¿Cómo puedes asegurarte de que el objeto de memoria compartida creado por tu clase SharedMemBase no se elimine en la construcción, pero que se elimine en la destrucción, incluso si ocurre una excepción no controlada en la función principal?

    Respuesta

    Para lograr esto, puedes crear una clase de utilidad separada, digamos ShmRemover, que tenga una única variable estática de miembro del tipo boost::interprocess::shared_memory_object. En el constructor de esta clase, creas el objeto de memoria compartida utilizando la opción boost::interprocess::create_only, y en el destructor de esta clase, eliminas el objeto de memoria compartida utilizando su nombre. También puedes hacer que esta clase de utilidad sea amiga de tu clase SharedMemBase, para que pueda acceder al nombre del objeto de memoria compartida.

    Luego, en tu clase SharedMemBase, puedes crear una instancia de esta clase de utilidad en el constructor, pasándole el nombre del objeto de memoria compartida. Esto asegurará que el objeto de memoria compartida se cree en la construcción de tu clase SharedMemBase, pero no se elimine hasta que se destruya el objeto ShmRemover en la salida del programa, independientemente de si hay o no una excepción no controlada en la función principal.

    Esto es lo que se vería el código:

    namespace bip = boost::interprocess;

    // Clase de utilidad para eliminar el objeto de memoria compartida al salir del programa
    // Nota: Esta clase requiere boost::interprocess versión >= 1.54
    class ShmRemover
    {
    public:
    ShmRemover(const std::string& name)
    : shm_(bip::create_only, name.c_str(), bip::read_write) {}

    ~ShmRemover()
    {
        bip::shared_memory_object::remove(shm_.get_name());
    }
    

    private:
    bip::shared_memory_object shm_;
    };

    class SharedMemBase
    {
    protected:
    bip::shared_memory_object shm_;
    const std::string name_;

    bip::shared_memory_object createShm(const std::string& name)
    {
        try
        {
            return bip::shared_memory_object(
                bip::open_or_create, name.c_str(), bip::read_write);
        }
        catch (const bip::interprocess_exception& e)
        {
            std::cerr << "Error al crear el objeto de memoria compartida con el nombre: " 
                << name << std::endl;
            throw e;
        }
    }
    

    public:
    SharedMemBase(const std::string& name)
    : name_(name),
    shm_(createShm(name))
    {
    // Crea una instancia de ShmRemover para asegurarte de que el objeto de memoria compartida no se elimine hasta la salida del programa
    static ShmRemover remover(name_);
    // Haz que ShmRemover sea amigo de esta clase para que pueda acceder a la variable de miembro name_
    friend class ShmRemover;
    }

    ~SharedMemBase()
    {
        // No hace nada aquí, ya que ShmRemover eliminará el objeto de memoria compartida
    }
    

    };

    int main()
    {
    SharedMemBase shm_obj(“nombre”);

    throw std::runtime_error("Algún error aleatorio no controlado");
    
    return 0;
    

    }

    En el código anterior, la clase ShmRemover crea el objeto de memoria compartida con la opción boost::interprocess::create_only en su constructor, lo que significa que fallará si otro proceso ya ha creado el objeto de memoria compartida con el mismo nombre. Esto asegura que tu clase SharedMemBase solo creará el objeto de memoria compartida si aún no existe, y fallará de manera adecuada si otro proceso ya lo ha creado.

Comments are closed.