Ключевое слово Volatile позволяет получить доступ к константным структурам в UnitTest ++

Я использую фреймворк UnitTest ++ для реализации модульных тестов некоторого кода C, за который я отвечаю. Конечный продукт встроен и использует константные структуры для хранения информации о конфигурации. Поскольку целевой хост может изменять конфигурацию асинхронно, все члены структуры являются энергозависимыми. Некоторые структуры также объявлены нестабильными.

У меня возникают ошибки сегментации, когда я использую const_cast, чтобы попытаться изменить экземпляры структуры, у которых отсутствует ключевое слово volatile на хосте UnitTest Windows 7. Для меня это имеет смысл. Однако, если экземпляр структуры был объявлен с ключевым словом volatile, тест проходит. Для меня это не имеет смысла.

Вот быстрый пример кода, который показывает проблему с gcc в Win7. Переключение значения определения вызывает появление segfault или нет, в зависимости от того, используется ли изменчивый экземпляр структуры или нет.

typedef struct
{
    volatile int foo;
    volatile int bar;
} TestStruct;

const TestStruct constStruct = { 1, 2};
volatile const TestStruct volatileConstStruct = { 3, 4};

#define SEG_FAULT 0

int main(void)
{
    TestStruct * constPtr = const_cast<TestStruct*>(&constStruct);
    TestStruct * constVolPtr = const_cast<TestStruct*>(&volatileConstStruct);

    #if(SEG_FAULT == 0)
        constVolPtr->foo = 10;
    #else
        constPtr->foo = 20;
    #endif
}

Может ли кто-нибудь помочь мне понять, почему ключевое слово volatile представляет собой обходной путь для segfault? Кроме того, может ли кто-нибудь предложить метод, позволяющий мне изменять значения в структуре для модульного теста без добавления ключевого слова volatile ко всем экземплярам структуры?

РЕДАКТИРОВАТЬ:

Я только что обнаружил, что это можно сделать на C:

#define const

Включение эффективного "const undefine" выше в тестовое приспособление позволяет моему целевому компилятору видеть ключевое слово const и правильно размещать структуры во флеш-памяти. Однако препроцессор компилятора UnitTest ++ удаляет ключевое слово const, поэтому мой тестовый прибор может изменять структуру.

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


person Egat    schedule 31.01.2012    source источник
comment
Вы смешиваете C и C ++ на уровне кода, а не только на уровне интерфейса, что, вероятно, плохая идея. Это два разных языка. В частности, их концепции о том, что является константой и что является const квалифицированным объектом, различаются.   -  person Jens Gustedt    schedule 01.02.2012
comment
Я использую UnitTest ++, для которого требуются модули C ++, для тестирования кода C. Я поместил весь смешанный C / C ++ в один и тот же файл для примера (я не могу поделиться фактическим кодом, над которым я работаю). В моей среде нет смешанного C / C ++.   -  person Egat    schedule 01.02.2012


Ответы (2)


Я считаю, что сноска в стандарте дает вам ответ. (Обратите внимание, что сноски не являются нормативными.)

В §6.7.3 стандартного проекта N1570:

132) Реализация может помещать неизменяемый константный объект в доступную только для чтения область памяти.

Это означает, что структура, определенная ключевым словом volatile, будет помещена в память для чтения и записи, несмотря на то, что она определена const.

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

Может ли кто-нибудь помочь мне понять, почему ключевое слово volatile представляет собой обходной путь для segfault? Кроме того, может ли кто-нибудь предложить метод, позволяющий мне изменять значения в структуре для модульного теста без добавления ключевого слова volatile ко всем экземплярам структуры?

Вы не можете. Объект const помещается в постоянную память, и вы вызовете segfault при записи в него. Либо отбросьте const, либо добавьте volatile - я настоятельно рекомендую отказаться от const.

person Lindydancer    schedule 31.01.2012
comment
Насколько я понимаю, const просто запрещает коду напрямую изменять данные. Поскольку я работаю над микро, константа используется, чтобы сообщить компилятору, чтобы он поместил данные во флеш-память. Его можно изменить, но не через прямой доступ. - person Egat; 01.02.2012

Почему такое странное поведение?
Изменение объекта const с помощью const_cast является неопределенным поведением.
const_cast используется, когда у вас есть const указатель на неконстантный объект и вы хотите навести на него указатель.

Почему это работает с volatile?
Не уверен. Однако это все еще неопределенное поведение, и вам просто повезло, что оно работает.

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

Как решить эту проблему?
Не объявляйте объекты, которые вы изменяете, как const. Поскольку вы собираетесь изменять их в ходе выполнения программы / теста, они не должны быть const. В настоящее время вы обещаете компилятору, что ваши объекты структуры неизменяемы (const), но позже вы нарушаете этот контракт, изменяя его. Дай это обещание, только если сможешь его сдержать.

person Alok Save    schedule 31.01.2012
comment
Я бы сказал, что const_cast используется для получения неконстантного указателя на константный объект, поскольку это типичный вариант использования. (Например, подумайте strchr для C ++.) - person Kerrek SB; 31.01.2012
comment
В C ++ есть константная перегрузка strchr, чтобы избежать этого. - person Bo Persson; 01.02.2012
comment
Спасибо, я не осознавал, что это неопределенное поведение. Как упоминалось ниже, я работаю со встроенным процессором. Структура помещается во флэш-память с помощью ключевого слова const. Мне нужно только изменить его, чтобы настроить параметры модуля, хранящиеся в структуре, для настройки модульных тестов. Мне придется найти другой способ обойти это, поскольку я не хочу полагаться на неопределенное поведение ключевого слова volatile, перемещающего хранилище в доступную для записи память. - person Egat; 01.02.2012
comment
Удаление ключевого слова const, вероятно, является лучшим ответом для большинства людей, сталкивающихся с подобной проблемой. Однако ответ lindydancer вытеснил ваш, поскольку он помог мне понять определение ключевого слова volatile в спецификации. Спасибо за помощь! - person Egat; 01.02.2012