Как защититься от переопределения символов

Мой проект включает в себя стек, который имеет ряд пользовательских типов (typedef). Проблема в том, что многие из этих определений типов противоречат нашим внутренним определениям типов. То есть используется то же имя символа. Есть ли способ защититься от этого?

Корень проблемы в том, что для использования стека в нашем приложении или кода оболочки, в зависимости от обстоятельств, должен быть включен определенный заголовочный файл. Этот заголовочный файл стека, в свою очередь, включает в себя файл определения типов провайдера стека. Это проблема. Они должны были включить свой файл определения типа через закрытый путь включения, но они этого не сделали. Теперь, есть очень много пользовательских типов конфликтов для очень распространенных имен, таких как BYTE, WORD, DWORD, и так далее.

3 ответа

Решение

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

По сути, я переделал включение необходимого заголовочного файла стека до включения нашего внутреннего файла определений типов. Затем между этими двумя включениями я добавил макрос компилятора, чтобы задать определенную константу в зависимости от того, было ли определено определение защиты заголовочного файла стека с одним включением. Затем я использовал эту условно определенную константу в качестве опции условной компиляции в нашем файле определения внутреннего типа, чтобы предотвратить переопределение конфликтующих типов данных. Это немного неаккуратно, но прогресс может быть достигнут только поэтапно.

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

Первое, что нужно сделать - это (очевидно) максимально ограничить количество имен в глобальном пространстве имен. Не используйте глобальные переменные, просто используйте статические, как пример.

Следующим шагом является принятие соглашения об именах для ваших модулей кода. Предположим, у вас есть "модуль ввода" в проекте. Затем вы можете, например, поставить префикс всех функций в модуле ввода "inp".

void inp_init (void); 
void inp_get  (int input);

#define INP_SOMECONSTANT 4

typedef enum
{
  INP_THIS,
  INP_THAT,
} inp_something_t;

И так далее. Всякий раз, когда эти элементы используются где-либо еще в коде, они будут иметь не только уникальный идентификатор, но и читателю будет очевидно, к какому модулю они принадлежат и, следовательно, к какой цели они имеют. Таким образом, исправляя конфликты пространства имен, вы одновременно получаете удобочитаемость.

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

Я предлагаю вам определить упаковочный заголовок, который переопределяет все функции и структуры, экспортируемые стеком, в терминах ваших собственных типов. Этот заголовок затем включается в ваши системные файлы, но не в файлы стека (где он будет конфликтовать). Затем вы можете скомпилировать и связать, но в интерфейсе есть слабое место. Если вы правильно выбрали типы в своих переопределениях, он должен работать правильно, оставляя только проблему с обслуживанием для каждого обновления от поставщика стека...

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