Как использовать макрос C (#define) для изменения вызовов, но не прототипов

Старый код в нашем приложении содержит призывы к malloc, realloc а также free, С нашим обновленным кодом наши собственные реализации вызываются вместо стандартных реализаций. Примеры приведены ниже,

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

Это прекрасно работает для обновленного кода и для более нового кода C++, мы просто реализуем глобальный new а также delete операторы, поэтому решение C++ "чище".

Проблема в том, что теперь мы должны включить стороннюю библиотеку, в которой есть классы, содержащие методы с такими именами, как malloc а также freeнапример,

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

Если свободный метод класса имеет одинаковое количество аргументов, препроцессор C/C++ просто заменяет все вхождения free от ourFreeдаже в определении класса, даже при вызове метода, свободного от класса ABC, Итак, определение класса выше и следующий вызов:

ABC abc;
abc.free(p);

заменены на,

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

ABC abc;
abc.OurFree(p);

Который может компилироваться, но который не связывает конечно.

Если ABC::free количество аргументов отличается от стандартного free, компилятор по-прежнему выдает предупреждение. мы хотели бы избежать их.

Некоторые альтернативные решения:

  • отмена определения в начале стороннего включаемого файла и переопределение его позже
  • убедитесь, что сторонний включаемый файл всегда включен до нашего собственного определения

Но даже в этом случае, если нашему коду требуется вызывать эти malloc или свободные методы сторонних классов, препроцессор все равно будет изменять вызовы, если мы не напишем все вызовы следующим образом:

(abc::free)(p)

Есть ли способ сказать, что препроцессор C/C++ определяет это?

  • должны быть заменены только чистые C-звонки
  • прототипы НЕ ДОЛЖНЫ быть заменены
  • методы в классах НЕ ДОЛЖНЫ заменяться

3 ответа

Решение

Препроцессор ничего не знает о масштабах и семантике. Такой короткий ответ - нет, вы не можете этого сделать.

Но вы можете использовать #undef free в библиотечных модулях. С другой стороны - это не поможет, если вы вызываете методы abc.free() из вашего кода.

Как насчет определения только этих замен для C, а не C++:

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

Почему бы вам просто не определить свои собственные функции malloc и free вместо использования макросов.

Итак, измените:

void *OutMalloc (size_t s)

чтобы:

void *malloc (size_t s)

так же, как вы можете перезаписать оператор new и удалить.

Я думаю, хотя я могу ошибаться, компоновщик будет искать в объектных файлах символы, прежде чем искать в библиотеках.

Другие вопросы по тегам