Ключовата дума volatile позволява достъп до const структури в UnitTest++

Използвам рамката UnitTest++ за внедряване на модулни тестове върху някои C кодове, за които отговарям. Крайният продукт е вграден и използва const структури за съхраняване на конфигурационна информация. Тъй като целевият хост може да променя конфигурацията асинхронно, всички членове на структурата са непостоянни. Някои от структурите също са декларирани като летливи.

Получавам грешки при сегментиране, когато използвам 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, така че моят тестов модул може да модифицира структурата.

Недостатъкът на това решение е, че не мога да добавя модулни тестове, които проверяват правилната константна работа на извиквания на функции. Въпреки това, тъй като премахването на const от екземплярите на struct не е опция (необходимо е данните да бъдат поставени във флаш), това изглежда е недостатък, с който ще трябва да живея.


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 просто забранява на кода да променя директно данните. Тъй като работя върху микро, const се използва, за да каже на компилатора да постави данните във флаш. Може да се променя, но не чрез директен достъп. - person Egat; 01.02.2012

Защо това странно поведение?
Модифицирането на const обект с помощта на const_cast е Недефинирано поведение.
const_cast се използва, когато имате const указател към непостоянен обект и искате да насочите показалеца си към него.

Защо работи с volatile?
Не съм сигурен. Въпреки това, това все още е недефинирано поведение и просто имате късмет, че работи.

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

Как да решите това?
Не декларирайте обектите, които модифицирате като const, тъй като възнамерявате да ги модифицирате по време на вашата програма/тест, те не трябва да бъдат const. В момента вие давате обещание на компилатора, че структурните ви обекти са неизменни (const), но по-късно нарушавате този договор, като го модифицирате. Направете това обещание само ако можете да го спазите.

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