Как использовать макрос C (#define) для изменения вызовов, но не прототипов - PullRequest
0 голосов
/ 23 февраля 2010

Более старый код в нашем приложении содержит звонки на 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 ]

2 голосов
/ 23 февраля 2010

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

#ifndef __cplusplus
#  define malloc(s) OurMalloc(s)
#  define free(p)   OurFree(p)
#endif
1 голос
/ 23 февраля 2010

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

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

void *OutMalloc (size_t s)

до:

void *malloc (size_t s)

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

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

0 голосов
/ 23 февраля 2010

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

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

...