¿C ++ mezclar nuevo / borrar entre libs?

Si utilizo la new palabra clave en mi biblioteca (que se construye de manera diferente a mi aplicación principal), cuando la elimino en mi aplicación principal con delete , ¿existe la posibilidad de que se produzca una falla / error?

si indeedy En particular, verá que los problemas con los montones de depuración / lanzamiento son diferentes, también si su biblioteca usa una ubicación nueva, o cualquier montón personalizado tendrá un problema. El problema de Debug / Release es, con mucho, el más común.

Depende. Si está hablando de una biblioteca estática, entonces probablemente estará bien, el código se ejecutará en el mismo contexto que el progtwig principal, utilizando la misma biblioteca de tiempo de ejecución de C ++. Esto significa que new y delete usarán el mismo montón.

Si está hablando de una biblioteca compartida (una DLL), entonces probablemente no estará bien. El código que se ejecuta en la DLL podría estar utilizando una biblioteca de tiempo de ejecución de C ++ diferente, lo que significa que el diseño del montón será diferente. La DLL podría estar usando un montón diferente por completo.

Llamar a delete (en el progtwig principal) en un puntero asignado por la DLL (o viceversa) dará lugar a (en el mejor de los casos) un locking inmediato o (en el peor de los casos) un daño en la memoria que llevará un tiempo localizarlo.

Tienes un par de opciones. El primero es usar el patrón “método de fábrica” ​​para crear y eliminar estos objetos:

 Foo *CreateFoo(); void DeleteFoo(Foo *p); 

Estos no deben ser implementados en el archivo de encabezado.

Alternativamente, puede definir un método Destroy en el objeto:

 class Foo { ~Foo(); public: virtual void Destroy(); }; 

… de nuevo, no implemente esto en el archivo de encabezado. Lo implementarías así:

 void Foo::Destroy() { delete this; // don't do anything that accesses this object past this point. } 

Tenga en cuenta que el destructor para Foo es privado, por lo que debe llamar a Foo::Destroy .

Microsoft COM hace algo similar, donde define un método de Release que elimina el objeto cuando su recuento de referencia cae a cero.

Sí lo harás. Una solución simple es proporcionar las funciones Crear y Eliminar en su biblioteca que se pueden llamar desde la aplicación principal. La función Crear ejecutará lo nuevo y devolverá un puntero, que luego se pasa a la función Eliminar para su eliminación.

Es un problema que solo he visto en Windows.

Los sistemas Unixish no tienen la costumbre de obligar a las bibliotecas compartidas a enlazar a diferentes versiones de la misma biblioteca dentro del mismo progtwig y todos los símbolos cargados son visibles a nivel mundial. Eso significa que si un objeto se asigna en una parte del código y se elimina en otra, ambos están usando la misma biblioteca del sistema para hacerlo.

Tengo que decir que este problema que Windows crea con sus diferentes DLL de tiempo de ejecución de C es realmente molesto y poco natural para un progtwigdor de C. Mira la biblioteca de C; tiene funciones como strdup que malloc la cadena y espera que el progtwigdor llame a free (). Pero haz lo mismo en tu propia biblioteca en Windows y espera la explosión. También tendrá que esperar, ya que no sucederá durante el desarrollo, sino solo después de haberle dado la DLL comstackda a algún otro pobre pobre.

Vieja cosa nueva ha cubierto esto antes. También da una lista de las principales soluciones de Microsoft.

Tienes toda la razón de que hay un problema allí, pero para la mayoría de los casos hay una solución aún más simple que las otras respuestas (hasta ahora) que han propuesto. Puede continuar usando nuevo y eliminar libremente: todo lo que necesita hacer es sobrecargar nuevo y eliminar para cada clase en su biblioteca que se pueda usar a través de los límites de DLL.

Personalmente, acabo de definir una clase simple para proporcionar la funcionalidad necesaria:

 class NewDelete { public: void *operator new (size_t size); void operator delete (void *memory); void *operator new (size_t size, void *ptr); void operator delete (void *memory, void *ptr); }; 

Siempre que esas cuatro funciones miembro estén definidas en la misma DLL, entonces cualquier clase que se derive de esta clase es automáticamente “segura para DLL”: las nuevas y las eliminaciones se pueden usar normalmente sin preocuparse por los límites de las DLL.