Ключевое слово Volatile позволяет получить доступ к константным структурам в UnitTest ++ - PullRequest
2 голосов
/ 31 января 2012

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

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

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

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, поэтому мой тестовый прибор может изменять структуру.

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

Ответы [ 2 ]

4 голосов
/ 31 января 2012

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

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

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

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

0 голосов
/ 01 февраля 2012

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

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

132) Реализация может размещать объект const, который не является энергозависимым в области хранения только для чтения.

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

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

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

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

...