Buenas prácticas para escribir bibliotecas dinámicas C [DSO] (compatibilidad binaria + gestión de memoria)

Tengo algo de experiencia escribiendo bibliotecas C, pero nunca he leído ningún documento formal que describa buenas prácticas al escribir dichas bibliotecas. Mi pregunta se refiere principalmente a 2 temas:

  1. ¿Cómo mantener la compatibilidad binaria? (He oído hablar del modismo pImpl, d-pointer)
  2. ¿Cómo diseñar interfaces que sigan siendo compatibles con versiones anteriores?

Lo principal sobre la compatibilidad binaria que puedo ver en mi investigación es que puedo hacer que las bibliotecas sean compatibles con el binario usando el idioma pImpl, pero cambiar la estructura / agregar nuevos miembros de datos, etc.puede afectar su compatibilidad binaria incluso mientras se usa pImpl. Además, ¿hay alguna manera de agregar nuevos métodos / funciones a una biblioteca sin romper la compatibilidad binaria? Supongo que agregar estas cosas cambiaría el tamaño y el diseño de la biblioteca, lo que rompería la compatibilidad.

¿Existe una herramienta para verificar la compatibilidad binaria?

Ya leí estos artículos. ¿Hay otros documentos que pueda leer detenidamente?

http://en.wikipedia.org/wiki/Opaque_pointer

http://techbase.kde.org/Policies/Binary_Compatibility_Issues_With_C++

Además, hay artículos que describen problemas de propiedad de la memoria en el contexto del diseño de interfaces de biblioteca. ¿Cuáles son las convenciones generales? ¿Quién posee la memoria, durante cuánto tiempo, quién es responsable de desasignar la memoria, etc.?

preguntado el 27 de agosto de 11 a las 20:08

Hiciste varias preguntas allí. Voy a responder a uno de ellos señalándote aquí: stackoverflow.com/questions/1969916/… -

¿Puedo preguntar, solo para mi propia información, por qué necesita la compatibilidad binaria del archivo lib? Cuando usted make su programa nuevamente con la nueva versión de la biblioteca, el enlazador mismo puede administrar cualquiera que sea la estructura de la nueva versión del archivo lib. ¿Puede explicarme para qué sirve la compatibilidad binaria? -

@Shahbaz - La pregunta es sobre binario compatibilidad, es decir, capacidad para corrida aplicaciones antiguas en una biblioteca compartida de nueva versión (* .so) sin volver a compilar. Habilidad para recompilar se llama fuente compatibilidad. -

4 Respuestas

Los problemas clave de compatibilidad son:

  • firmas de funciones
  • formato de los datos a los que acceden tanto la biblioteca como la persona que llama
  • variables globales en la biblioteca a la que accede la persona que llama
  • código de biblioteca que termina en la persona que llama debido a macros / funciones en línea en los encabezados
  • #define/enum valores constantes en encabezados compartidos

Entonces, la mejor lista de pautas que puedo dar es:

  • Nunca cambie la firma (tipos de retorno / argumento) de ninguna interfaz pública. Si necesita expandir una interfaz, en su lugar agregue una nueva función que tome más argumentos (piense dup frente a dup2 or wait frente a waitpid).
  • En la medida de lo posible, use punteros a objetos de datos opacos completamente encapsulados y ni siquiera exponga la definición de tales estructuras en los encabezados públicos (hágalos incompletos struct tipos).
  • Cuando desee compartir una estructura, haga que la persona que llama nunca declare variables de ese tipo de estructura y, en su lugar, llame a funciones de asignación / libre explícitas en la biblioteca. Nunca cambie el tipo de miembros existentes ni elimine miembros existentes; en su lugar, agregue nuevos miembros solo al final de la estructura.
  • No exponga las variables globales de las bibliotecas, punto. A menos que comprenda las "reubicaciones de copias", es mejor no preguntar por qué. Simplemente no lo hagas.
  • No coloque funciones en línea o macros que contengan código en los encabezados públicos de su biblioteca a menos que use la interfaz expuesta y documentada que se mantendrá permanente. Si tocan las partes internas de los objetos de datos opacos, causarán problemas cuando decida cambiar las partes internas.
  • No renumerar los existentes #define/enum constantes. Solo agregue nuevas constantes con valores no utilizados anteriormente.

Si sigue estas pautas, creo que tiene al menos un 95% de cobertura.

Respondido 28 ago 11, 01:08

¿Por qué agregar una nueva función no rompe la compatibilidad binaria de los DSO? ¿Existe alguna documentación que consulte para averiguar por qué se rompe la compatibilidad binaria cuando se cambian ciertas cosas en un DSO? Esto me ayudará a obtener una comprensión más profunda. Gracias. - void_ptr

Creo que lo que estás diciendo es demasiado duro. En mi opinión, ocultar cosas al usuario de esa manera es demasiado. La cosa es que no puedes decir: ¿Qué pasa si el usuario cambia la variable que no debería? Bueno, si lo hacen y el programa se rompe, ¡es culpa suya! Usted sabe que el mismo programador también puede dividir por cero, pero nuevamente es culpa suya y no su responsabilidad. - Shahbaz

@Shahbaz: Creo que no entendiste el punto. Si hace que cada detalle de la implementación sea parte de la interfaz, se verá obligado a mantener los detalles de la implementación fijos permanentemente oa romper la compatibilidad binaria cuando los cambie. La pregunta de OP era sobre no romper la compatibilidad binaria, por lo que las opciones que quedan son seguir mi consejo o comprometerse a nunca cambiar los componentes internos de la implementación ... - R .. GitHub DEJA DE AYUDAR A ICE

@R ..: Quizás me estoy perdiendo algo. No estoy exactamente seguro de qué es la compatibilidad binaria y por qué la quiere (vea mi comentario sobre la pregunta) - Shahbaz

La compatibilidad binaria significa que cambiar a una nueva versión de la biblioteca no romperá las aplicaciones que fueron compiladas / vinculadas con una versión anterior. Es bueno para que la gente no tenga que quedarse N diferentes versiones de cada biblioteca (que se convierte fácilmente N^M tan pronto como las bibliotecas empiecen a depender unas de otras ...). - R .. GitHub DEJA DE AYUDAR A ICE

¿Existe una herramienta para verificar la compatibilidad binaria?

Verificador de cumplimiento ABI - una herramienta para comprobar la compatibilidad binaria con versiones anteriores de una biblioteca compartida C / C ++ (DSO).

¿Hay otros documentos que pueda leer detenidamente?

Ver esto largo lista de articulos sobre la compatibilidad binaria de bibliotecas compartidas.

¿Cómo diseñar interfaces que sigan siendo compatibles con versiones anteriores?

Uso de reservado / relleno fields es un método general para preservar la compatibilidad de C Bibliotecas. Pero también hay muchos otros.

Además, ¿hay alguna manera de agregar nuevos métodos / funciones a una biblioteca sin romper la compatibilidad binaria? Supongo que agregar estas cosas cambiaría el tamaño y el diseño de la biblioteca, lo que rompería la compatibilidad.

Adicional C las funciones no rompen la compatibilidad binaria con versiones anteriores de DSO en Linux y Mac. Lo mismo ocurre con Windows y Symbian, pero debe agregar nuevas funciones solo al final de un archivo .DEF. Sin embargo, la compatibilidad hacia adelante siempre se rompe con funciones adicionales.

Adicional C + + Los métodos rompen la compatibilidad binaria si y solo si son virtual or puramente virtual unos, porque el diseño de tabla v podría cambiar. Pero tu pregunta parece ser sobre C bibliotecas solamente.

Respondido 17 ago 15, 22:08

En particular, el # 19 en la lista de artículos, dsohowto de Ulrich Drepper es una muy buena introducción a la escritura de buenas bibliotecas compartidas. - Janneb

Un par de cosas para agregar a lo que dijo R.

Dado que parece que estás hablando de ABI de C y no de ABI de C ++:

cambiar la estructura / agregar nuevos miembros de datos, etc.puede afectar su compatibilidad binaria incluso mientras se usa pImpl

Ese no debería ser el caso cuando se usa pIMpl: si los usuarios externos del objeto solo tienen un puntero / identificador opaco al objeto y solo la biblioteca se ocupa de las partes internas de la estructura, entonces, por definición, lo que se ocupa de las partes internas de la estructura es compatible con ella.

¿Hay alguna manera de agregar nuevos métodos / funciones a una biblioteca sin romper la compatibilidad binaria? Supongo que agregar estas cosas cambiaría el tamaño y el diseño de la biblioteca, lo que rompería la compatibilidad.

Agregar nuevas funciones o cambiar el tamaño o el diseño de la biblioteca compartida no rompe la compatibilidad binaria. Dado que el enlace a la dirección de la función no se realiza hasta que la biblioteca compartida se carga en el proceso, un cambio en la ubicación de la función de destino no es un problema.

Respondido 28 ago 11, 02:08

En cuanto a documentación, Cómo escribir bibliotecas compartidas de Ulrich Drepper es una lectura obligada.

Respondido 29 ago 11, 09:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.