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.

VS2019 | C++ | Punteros compartidos | Advertencia del compilador: El puntero apunta a memoria asignada en la pila.

He heredado un montón de código C++, saturado de std::shared_ptrs, la mayoría [¿todos?] de los cuales son innecesarios y, sospecho, están degradando el rendimiento. No es factible cambiar todo de una vez, así que estoy cambiando el código por tramos y realizando pruebas de rendimiento.

Un problema con el que me encuentro es la interfaz en la jerarquía de métodos entre mi nuevo código de puntero “raw” y el underlying de shared_ptr. Un ejemplo ficticio (sé que se podría simplificar…):

SomeObject *MyClass::GetSomeObject(const std::string& aString)
{
  //para los métodos del shared pointer subyacente
  std::shared<em>ptr<std::string> tmpString = make</em>shared<std::string>(aString);

//llamar al método usando mi shared pointer local
  std::shared_ptr<SomeObject> someObj = GetTheObject(tmpString);

//La línea de abajo da una advertencia del compilador: "El puntero apunta a una memoria asignada en la pila"
  return someObj.get(); // un puntero a un objeto en std::map
}

Sé que GetTheObject() está devolviendo un puntero a un objeto en un std::map persistente, por lo que la memoria estará en buen estado después de que salgamos de GetSomeObject() y el shared pointer [y su puntero raw envuelto] hayan salido de ámbito.

No tengo la costumbre de ignorar advertencias, ASÍ QUE:

Preguntas:
1. ¿Es la advertencia porque el compilador está preocupado por el ámbito del shared pointer en lugar del objeto apuntado? [es decir, ¿puedo ignorarla en este caso?]

  1. Si es un problema real, ¿hay alguna forma ingeniosa de solucionarlo (que no involucre construir clases envolventes y demás soluciones alternativas…)?
Tags:  , , ,

Answer

  1. Avatar for davy.ai
    1. Sí, la advertencia se debe a que el puntero está apuntando a una memoria asignada en la pila, dentro del alcance del puntero compartido. Esto significa que una vez que el puntero compartido queda fuera de alcance, la memoria a la que apunta será liberada y acceder al puntero sin procesar puede llevar a un comportamiento indefinido. Aunque en este caso específico, dado que sabes que el objeto apuntado persistirá, es seguro ignorar la advertencia.
    2. Si deseas evitar la advertencia sin construir clases de envoltura o modificar significativamente el código existente, puedes usar una sobrecarga del constructor de shared_ptr que toma un eliminador personalizado como parámetro. En este caso, podrías crear un shared_ptr con un eliminador personalizado que no haga nada, luego usarlo para envolver el puntero sin procesar devuelto por someObj.get(), de modo que la memoria a la que apunta sea gestionada por el mismo mecanismo que el resto de los shared_ptr en la base de código. Esto se vería algo así:

      SomeObject *MyClass::GetSomeObject(const std::string& aString)
      {
       std::shared_ptr<std::string> tmpString = std::make_shared<std::string>(aString);
       std::shared_ptr<someobject> someObj = GetTheObject(tmpString);
       return std::shared_ptr<someobject>(someObj.get(), [](SomeObject*){}).get();
      }
      

      Aquí, la función lambda pasada como eliminador personalizado toma un SomeObject* como su parámetro y no hace nada con él, lo que efectivamente lo convierte en una operación sin efecto.

      Sin embargo, hay que tener en cuenta que este enfoque aún puede tener un cierto costo adicional debido a la gestión adicional de shared pointer involucrada, por lo que no necesariamente mejorará el rendimiento. Además, modificar el código existente para eliminar los shared pointer innecesarios aún puede ser una mejor solución a largo plazo.

Comments are closed.