LINUX.ORG.RU

C: warning: volatile pointer


0

0

=== test.c ===
static volatile char *vp;

int main(int argc, char *argv[])
{
    struct {char *p;} st;

    /* lock */
    st.p = vp;
    /* unlock */
    return 0;
}
======

Присвоение st.p = vp; не должно быть оптимизировано компилятором (hint volatile должен действовать).

> gcc test.c
test.c: In function `main':
test.c:9: warning: assignment discards qualifiers from pointer target type

Поменять структуру st не могу (сделать volatile char *p;).
Привёл к типу: st.p = (char *) vp;

> gcc -Wcast-qual test.c
test.c: In function `main':
test.c:9: warning: cast discards qualifiers from pointer target type

Как избежать warning'ов?
Заранее спасибо.
anonymous
Ответ на: комментарий от php-coder

> После этого компилится молча (не знаю работает ли :)) )

Оно у тебя вообще работает не так, как ты думаешь. Тебе надо именно volatile char *p делать, а если "не могу", то что ж -- значит, не смогла.

:(

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

Die-Hard ★★★★★
()

> Присвоение st.p = vp; не должно быть оптимизировано компилятором (hint volatile должен действовать).

volatile действует на то на что указывает vp. st.p = vp может быть оптимизировано.

А варнинг по понятной причине: vp помечен как указатель на volatile, после присваивания метка volatile с него снимается -- вот и ворнинг. Объясни зачем тебе volatile.

Ты уверен, что понимаешь разницу между volatile char *vp; и char *volatile vp; ?

dilmah ★★★★★
()
Ответ на: комментарий от Die-Hard

Вдогонку -- компилятор-то не будет, но процессор может переупорядочить, если барьер не ставить.

Если процессор отличен от x86, то, возможно, нужен барьер; при присваивании волатильной переменной компилятор его, если надо, вставляет. Если речь идет об x86 (пентиум, атлон, зеон, оптерон итд), то ничего не нужно. Если итаник или альфа -- однозначно нужен барьер, про другие процессоры я не в курсе.

Die-Hard ★★★★★
()
Ответ на: комментарий от wfrr

> Вот интересно ...

Какой-то поток сознания дилетанта, из которого мало что можно вынести...

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

Die-Hard ★★★★★
()
Ответ на: комментарий от wfrr

> Что там не верно?

Да все там верно, просто много-много буков и сомнений вокруг проблемы, прочитать про которую можно в любом учебнике, и при этом выводы какие-то "размазанные".

Надо просто отдавать себе отчет в том, что такое volatile и понимать следующие 3 вещи:

1. Нарушение порядка операций проистекает из трех причин: а) оптимизация компилятором, б) переупорядочивание операций процессором и в) некогерентное кэширование при СМП.

2. Все thread-related синхронизационные примитивы написаны так, чтобы все эти моменты правильно учитывать, иначе -- глюк, топик для багрепорта.

3. Компиляторы понимают, что, если видят модификатор volatile, надо сгенерить код не только не оптимизирующий операции с волатильной переменной, но и учитывающий б)и в), иначе -- глюк, топик для багрепорта.

Еще полезно знать, что компилятор обычно не оптимизирует через вызовы функций.

Die-Hard ★★★★★
()
Ответ на: комментарий от Die-Hard

> Тебе надо именно volatile char *p делать...

Использую из структуру внешней библиотеки.

> Ты уверен, что понимаешь разницу между volatile char *vp; и char *volatile vp; ?

Мне нужно пометить volatile'ом сам указатель, а не объект, на который указывает vp. Т.е. несколько нитей могут поменять указатель (напр., это указатель на начало списка - header of linked list) и я не уверен, что компилятор не сохранит указатель в регистре до блокировки (lock).

anonymous
()
Ответ на: комментарий от anonymous

> и я не уверен, что компилятор не сохранит указатель в регистре до блокировки (lock).

Забудь про volatile! Перед блокировкой компилятор все сбросит.

Die-Hard ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.