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

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

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


person Jim Fell    schedule 06.11.2012    source источник
comment
Можете ли вы поместить обертку вокруг стека?   -  person William Morris    schedule 07.11.2012
comment
@WilliamMorris Это то, что я пытаюсь сделать, поэтому эти различия необходимо разрешить.   -  person Jim Fell    schedule 07.11.2012
comment
Корень проблемы в том, почему у вас возникают конфликты имен? В стеке не используется какое-либо правильное соглашение об именах, или это приложение, или и то, и другое? Есть ли конфликты со стандартной библиотекой C (ошибки)?   -  person Lundin    schedule 07.11.2012


Ответы (3)


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

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

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

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

#define INP_SOMECONSTANT 4

typedef enum
{
  INP_THIS,
  INP_THAT,
} inp_something_t;

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

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

person Lundin    schedule 06.11.2012
comment
Я не думаю, что это решает проблему. Насколько я понимаю, две стороны системы определяют типы с одинаковыми именами. Это означает, что входной стек не может включать системные заголовки, а система не может включать заголовки стека из-за ошибок переопределения. Даже если они определяют типы одинаково, включая противоположные заголовки, они не будут компилироваться. - person William Morris; 07.11.2012
comment
@WilliamMorris Стек не будет включать остальную часть приложения, это не имеет смысла. Вероятно, это какой-то стек коммуникационных протоколов, TCP/IP, CANopen, Ethernet и т.д. Он будет находиться на нижних аппаратных уровнях программы, а вызывающим является фактическое приложение. Ответственность за предотвращение конфликтов имен лежит на вызывающем объекте. Во всяком случае, это не очевидно с ограниченной информацией, указанной в вопросе. - person Lundin; 07.11.2012
comment
Нет, я знаю, что стек не будет включать заголовки приложений. Но представьте, что вы хотите написать оболочку, чтобы объединить их. Вы хотите включить заголовки стека, преобразовать их функции в свои типы, а затем экспортировать преобразованные функции. Но вы не можете, потому что, когда вы пытаетесь включить свои собственные заголовки в оболочку, а также заголовки стека, они конфликтуют. - person William Morris; 07.11.2012
comment
@Lundin Спасибо за продуманные предложения. Реализованное вами соглашение об именах очень похоже на то, что я применяю в модулях, которые я кодирую. Недавно меня наняла очень маленькая компания в качестве первого инженера, полностью посвятившего себя разработке прошивки. Ситуация такова, что большая часть их существующей кодовой базы ... требует внимания. - person Jim Fell; 07.11.2012
comment
@JimFell Я сам очень хорошо знаком с этой ситуацией :) Создать формальный стандарт кодирования в одиночку в небольшой компании - это много работы, но в конце концов оно того стоит. Я настоятельно рекомендую использовать MISRA-C в качестве базу, выберите из нее то, что вам нравится, а затем, в качестве следующего шага, определитесь с форматированием кода и правилами именования. - person Lundin; 07.11.2012

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

person William Morris    schedule 06.11.2012

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

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

person Jim Fell    schedule 06.11.2012
comment
Это делает ваш проект подчиненным стеку, что звучит странно. Если стек изменяет свои определения несовместимым образом, вам, возможно, придется изменить файл определений типов вашего проекта (довольно важный файл, я думаю), а не просто изменить файл-оболочку, который я предложил. Скорее всего, таких изменений не произойдет, поэтому проблемы не возникнет, но я бы предпочел зависимость наоборот :-) - person William Morris; 07.11.2012
comment
Обратите внимание, что ваше решение также означает, что некоторые из ваших исходных файлов и любые заголовки, которые они включают, будут скомпилированы с определениями типов, которые поступают из проекта, а другие, те, которые используют стек (и любые заголовки, которые они включают), будут скомпилированы с определениями типов. которые происходят в стеке. Это может привести к тонким ошибкам, которые трудно найти... - person William Morris; 07.11.2012
comment
@WilliamMorris Спасибо, но это цель кода-оболочки, по крайней мере, в том, что касается моего проекта. Действительно, стек может измениться в более поздних версиях, и код оболочки необходимо будет соответствующим образом изменить. Однако это все, что нужно изменить. У меня есть настройка кода-оболочки с общедоступными и частными включаемыми файлами, так что другим проектам, использующим сгенерированную библиотеку, не придется иметь дело с этим беспорядком. - person Jim Fell; 07.11.2012