Cómo usar las macros de C (#define) para alterar las llamadas pero no los prototipos

El código anterior en nuestra aplicación contiene llamadas a malloc , realloc y free . Con nuestro código actualizado, nuestras propias implementaciones se llaman en lugar de las de tiempo de ejecución estándar. Los ejemplos se muestran a continuación,

 #define malloc(s) OurMalloc(s) #define free(p) OurFree(p) 

Esto funciona bien para el código actualizado y para el código C ++ más reciente, simplemente implementamos operadores globales new y delete , por lo que la solución C ++ es “más limpia”.

El problema es que ahora tenemos que incluir una biblioteca de terceros, que tiene clases que contienen métodos que tienen nombres como malloc y free , por ejemplo

  class ABC { public: ... void free (char *p); }; 

Si el método libre de la clase tiene el mismo número de argumentos, el preprocesador C / C ++ simplemente reemplaza todas las apariciones de free por ourFree , incluso en la definición de la clase, incluso cuando se llama al método libre de la clase ABC . Así que la definición de clase anterior y la siguiente llamada:

 ABC abc; abc.free(p); 

son reemplazados por,

 class ABC { public: ... void OurFree (char *p); }; ABC abc; abc.OurFree(p); 

Que puede comstackr, pero que no se vincula, por supuesto.

Si ABC::free tiene un número diferente de argumentos que el estándar gratuito, el comstackdor sigue dando una advertencia. Nos gustaría evitarlos.

Algunas soluciones alternativas son:

  • Undefining nuestro define al principio del archivo de inclusión de terceros y redefinirlo más tarde
  • asegúrese de que el archivo de inclusión de terceros se incluya siempre antes de nuestra propia definición

Pero incluso entonces, si se requiere que nuestro código llame a estos métodos malloc o gratuitos de las clases de terceros, el preprocesador todavía alterará las llamadas, a menos que escribamos todas las llamadas de esta manera:

 (abc::free)(p) 

¿Hay alguna manera de decirle a un preprocesador C / C ++ que lo defina?

  • solo deben reemplazarse las llamadas C puras
  • Los prototipos NO DEBEN ser reemplazados
  • Los métodos en las clases NO DEBEN ser reemplazados

El preprocesador no sabe nada sobre scope y semántica. Tan breve respuesta – no, no puedes hacer eso.

Pero, puede usar #undef free en los módulos de la biblioteca. Por otro lado, esto no servirá de nada si llama a métodos abc.free() desde su código.

¿Qué tal si solo definimos esos reemplazos para C y no para C ++?

 #ifndef __cplusplus # define malloc(s) OurMalloc(s) # define free(p) OurFree(p) #endif 

¿Por qué no define sus propias funciones malloc y gratuitas en lugar de usar macros?

Entonces, cambio:

 void *OutMalloc (size_t s) 

a:

 void *malloc (size_t s) 

de la misma manera que puede oprimir el operador nuevo y eliminar.

Creo que, aunque pueda estar equivocado, el vinculador buscará símbolos en los archivos de objetos antes de buscar en las bibliotecas.